使机器运转起来

“科技是第一生产力”,科技发展将人类从枯燥无味的工作中解放出来。机器学习的目的同样如此,让计算机代替人类进行预测、模拟或分类。 这是关于机器学习算法的handbook,大致介绍了机器学习算法的基础内容、经典回归算法、经典分类算法、自然语言处理、集成算法、无监督学习算法、神经网络算法。 每个章节都包含算法原理的讲解和基于python语法的操作演示,希望这个小册子能对您有所帮助😊


|作者|于阳|


使机器运转起来总论简单介绍机器学习与因果推断机器学习关键术语有监学习与无监学习基本原理过拟合和欠拟合偏差和方差泛化特点与应用特点应用经典回归算法OLS回归算法OLS基本原理OLS算法的操作代码岭回归算法岭回归算法的基本原理岭回归算法的操作代码Lasso回归算法Lasso回归算法的基本原理Lasso回归算法的操作代码算法调参验证集法交叉验证法岭回归和Lasso回归的调参算法调参的操作代码经典分类算法K临近算法K临近算法的基本原理K临近算法的操作代码朴素贝叶斯算法朴素贝叶斯算法的基本原理朴素贝叶斯算法的操作代码决策树算法决策树算法的基本原理决策树算法的操作代码支持向量机算法支持向量机算法的基本原理支持向量机算法的操作代码分类算法的评估准确率和错误率混淆矩阵、精准率、召回率、F1分数ROC曲线和AUC自然语言处理分词分词的基本原理分词的操作代码TF-IDFTF-IDF的基本原理TF-IDF的操作代码文本相似度文本相似度的基本原理文本相似度的操作代码集成算法随机森林随机森林的基本原理随机森林的操作代码梯度提升树算法梯度提升树算法的基本原理梯度提升树算法的操作代码XGBoostXGBoost算法的基本原理XGBoost算法的操作代码无监督学习算法聚类算法K-means聚类算法层次聚类算法DBSCAN聚类算法降维算法主成分分析算法的基本原理主成分分析算法的操作代码LDA主题模型LDA主题模型的基本原理LDA主题模型的操作代码神经网络算法神经网络算法的基本原理神经网络算法的基本原理神经网络算法的数学推导前馈神经网络算法前馈神经网络的回归问题前馈神经网络的分类问题卷积神经网络算法卷积神经网络的基本原理卷积神经网络的操作代码递归神经网络算法递归神经网络的基本原理递归神经网络的操作代码

总论

简单介绍

机器学习与因果推断

机器学习的指向是预测,即以历史数据为基础,通过X去预测Y。(泛化是机器学习的重要概念,指调试的算法具有适用性,能够对未知数据进行预测

因果推断的指向是关系,通过构建因果关系验证假设。

机器学习关键术语

因果推断机器学习
自变量、解释变量表征、特征
因变量、被解释变量响应
观测值案例
模型算法

有监学习与无监学习

有监督学习是根据已有数据集,知道输入和输出结果之间的关系,并根据这种关系训练得到一个最优模型(既有特征也有标签)。

无监督学习处理的是只有输入变量,没有相应的输出变量的训练数据。

基本原理

过拟合和欠拟合

过拟合是指,算法在训练样本中过于优越,导致在测试数据集中表现不佳。

狸花猫
橘猫与柯基犬

例如,根据特征识别出猫和狗,但训练集中都是狸花猫的数据,因而训练集中的算法表现十分优秀。 但当测试集中不再是狸花猫的数据而是橘猫时,算法准确度就会变得很糟糕,难以分辨这是猫还是柯基犬。

欠拟合是指,算法在训练集和测试集中的表现都不好(包含了太多无意义的噪音)。

偏差和方差

由于机器学习的重点是预测。因此,判断算法好坏即估计值与真实值之间的差距,在机器学习中称为偏差(Bias,其定义为:

(1)Bias=Ef^(x)f(x)

其中f(x)^为给定x的估计值,f(x) 为真实值。

方差是衡量在大量抽样过程中,估计量f(x)^本身围绕着其期望Ef^(x)的波动幅度,其定义为:

(2)Var=E[f^(x)Ef^(x)]2

事实上,算法的预测能力取决于均方误差(MSE)

(3)MSE(f^(x))=E[(yf^(x)]2=E[(f(x)+ϵf^(x)]2(4)=E[f(x)Ef^(x)+Ef^(x)f^(x)+ϵ]2(5)=[Ef^(x)f(x)]2+E[f^(x)Ef^(x)]2+E(ϵ2)(6)=Bias2+Variance+Var(ϵ)

也就是说,算法的预测性能同时受偏差和方差影响。一般来说,偏差小而方差大,会出现“过拟合”;偏差大而方差小则是“欠拟合”。

偏差和方差 总的来说,偏差表示算法是否准确,方差表示算法是否稳定。

泛化

泛化是机器学习的首要目标,甚至是唯一目标。由于偏差和方差之间是此消彼长的关系,因此如何实现二者之间的最优是个难题。在这过程中,机器学习有三个最重要的方式以实现目标。

(1)正则化

在我们进行预测中,会用到最小二乘法。基于高斯-马尔可夫定理,我们很容易得到无偏估计,但无偏估计并不一定等于最优估计量。以最小二乘法建模时,我们的偏差为0,方差为σ2。当模型过于复杂,σ2会变得非常大,此时模型处于过拟合状态,泛化性能很低。因此需要通过引入惩罚项牺牲无偏性以减小方差,这个思路就叫做正则化。正则一词的本意为“使某物变得规则、标准或规范”,正则化就是使过拟合的模型变得更简单、规范,以避免模型在训练数据上学习到不必要的复杂性或噪声。

其中,最常用的正则化方式为岭回归和Lasso回归。具体来说,岭回归和Lasso回归都是在OLS的目标函数基础上加上惩罚项:

(7)岭回归:min(i(yiXiTβ)2+λi=1pβj2)(8)Lasso回归:min(i(yiXiTβ)2+λi=1p|βi|)

惩罚项是对过拟合模型的一种“惩罚”,目的是限制模型的自由度。试想一下,你在一个城市的路上开车,目标是找到一个最佳路径,但你不能在每个街道上都停下来(过拟合),你希望找到一个尽可能简短、平稳的路径来避免走冗余的弯路。惩罚项就像是在路径的每个转弯点施加了一个“罚款”,每次转弯越多(模型越复杂)就要支付更多的“罚款”,最终你会选择一个更加简单、平稳的路径。

(2)集成算法

简单来说,集成算法的核心就是通过一些方式提高算法的预测性能(力大砖飞),例如,进行多次有放回的抽样求平均值。

(3)深度学习法

以神经网络为例,进行多次嵌套。

特点与应用

特点

机器学习有以下几种优势与特点:

处理高维数据、处理非结构化数据、处理非线性关系、强调模型的泛化性能、对异质性估计重视、数据驱动。

应用

机器学习的主要应用范围:

预测、生成数据(将海量的非结构化数据处理成社会科学能够使用的结构数据)、因果识别。


经典回归算法

OLS回归算法

OLS基本原理

最小二乘法

OLS(Ordinary Least Squares)的思想极其简单,在一群散点间我们能够画出无数条直线,我们希望其中一条直线能够使所有点到直线的距离最短,即残差和最小。由于散点不规则地分布在直线的上下两侧,因此残差必然会出现正负值,而我们很难比较1+1=00.5+0.5=0之间谁的残差和更小,为此我们对残差取平方,比较其平方和大小。因为我们追求的是残差平方和最小,所以这个方法就叫做最小二乘法。

通过计算残差,即观测值与期望值之间的差距,使得残差平方和最小而形成一条拟合曲线,其目标函数为:

(9)min(i(yiXiTβ)2)

当OLS是BLUE(Best Linear Unbiased Estimator)时:

(10)Biasols=E(^β)β=0,Varols=σ2

因此,即便通过OLS预测得到的估计系数是无偏的,但方差大的缺点依旧让该方法在预测性能上表现较差。当然,其优点在于简单易用、参数估计无偏性和有效性、估计参数容易解释(参数=特征变量对相应变量的边际影响)。

OLS算法的操作代码

我们用sklearn模块自带的糖尿病数据集进行演示,该数据集收集了442位糖尿病人的10个特征,用以预测糖尿病人的病情。

一般来说,使用python对OLS回归算法进行数据分析时,有六个步骤:

(1)导入模块并加载数据

首先,调用pandas、numpy和sklearn。

接着从load_diabetes()加载数据,并查看数据特征。

(2)指定特征变量和响应变量

示例中为糖尿病人的数据集,一共442条数据。其中,data是数据集中的特征变量,一共10个,类型为NumPy数组;target为数据集中的目标变量,同样也是NumPy数组。

(3)划分训练集和测试集

为了强化算法的预测性能,机器学习会将样本划分成训练集和测试集。首先,机器学习会在训练集中训练模型,得到参数估计值,然后将训练后的模型应用到测试集中,用于观察模型的预测能力。

一般来说,训练集和测试集的划分没有客观统一的标准,我们可以通过test_size进行调节。如果不指定test_size,则会默认训练集和测试集比为3:1。

(4)使用训练集训练模型

在划分完训练集和测试集后,使用训练集来建模。首先定义一个算法,即实例化一个对象,在本示例中为建立线性回归模型。然后利用训练集X_trainy_train来训练这个模型。

(5)评估模型预测性能

训练完模型后,需要评估模型的预测性能。对于线性回归而言,一般使用测试集上的均方误差(MSE)或均方误差平方根(RMSE)。其中,MSE(y^)=E(y^y)2RMSE=MSE。MSE和RMSE越小,则算法的预测性能越好。

(6)调整参数选择最优模型

一般而言,为了得到预测性能最佳的模型需要多次调整超参训练模型,每次都会得到一个MSE或RMSE。将这些进行对比,选择MSE或RMSE最小以获得最终训练的模型。在示例中,我们将特征变量转变成dataframe后,选择bmi、bp、s5这几个特征,观察是否会提升模型的预测性能。

岭回归算法

当我们需要面临的处理数据不再是简单的调查数据,而是海量大数据与高维数据,甚至出现变量数量超过样本的情况时,再使用OLS回归算法会存在十分严重的共线性问题。因为β^=(XX)1XYβ^的求解依赖于(XX)1是否可逆。在多重共线性的情况下,X存在线性相关,即(XX)是个奇异矩阵不再可逆,因而β^不存在唯一解。想要规避该问题,我们需要进行正则化。

岭回归算法的基本原理

(1)岭回归算法的原理

在总论的泛化部分,我们提到过岭回归的目标函数为:

(11)f=i(yiXiTβ)2+λi=1pβj2

等式右边第二项是对所有待估计系数β求平方和(L2范数惩罚项)乘上一个调节参数(超参数λ。其中,调节参数λ0。参考OLS的思想,我们需要使目标函数最小,因此λ越大表明对模型复杂程度的惩罚力度越大,会更大程度的收缩系数β的估计值;当λ时,惩罚力度极大,系数估计值β0;当λ=0时,岭回归算法会回退到OLS回归算法。

我们将目标函数重写成:

(12)min((YXβ)T(YXβ)+λβTβ)

为找到最小化目标函数,我们对β求导并令其等于0:

(13)β((YXβ)T(YXβ)+λβTβ)=0(14)2XT(YXβ)+2λβ=0(15)XTXβXTY+λβ=0(16)(XTX+λI)β=XTY(17)(XTX+λI)1XTY=β

由于λI为正定矩阵,XTX+λI可逆,因此β存在唯一解。

为了更直观理解惩罚含义,我们以几何形式进行解释。公式12可以等价改写成:

(18)mini=1n(yiXβ^)2s. t. βj2t

其中,t0。换言之,我们相当于需要在估计系数平方和不大于t这个条件下,根据最小化残差平方和求解参数。在二维空间下,约束条件等同于以t为半径的圆,即β12+β22=t

残差平方和的等值线可以表示为:

(19)i=1n(yi(xi1β1+xi2β2)2)=C

其中,C是一个常数,表示残差平方和的某个固定值。因而β的所有可能取值的几何图形是一个椭圆形。

岭回归几何图形

从图中我们可以更直观理解,如果要在圆形组成的可行解中将残差平方和最小化,那么最优解一定产生于圆形曲线与椭圆形曲线的交点,即岭回归的系数估计值。

同时,从图中也可以看到,在加入惩罚项后系数会向0收缩,但并不至于收缩至0。

(2)岭回归算法的预测能力

从估计值可知,β^ridge=β^ols/(1+λ),即在加入惩罚项的情况下系数一定是有偏的。但相对而言,其系数的方差会缩小至σ2/(1+λ)。也就是说,岭回归算法相较于OLS算法牺牲了模型的无偏性,降低了模型的方差,从而得到更好的样本之外的预测能力。

(3)岭回归的优缺点

岭回归算法相较于OLS回归算法有几个突出的优点:

解决多重共线性问题防止过度拟合能够处理高维数据集易于实现与计算

但同时,岭回归也有一些无法忽视的缺陷:

调节参数选择困难(λ值究竟取多少最合适假设线性关系不能自动选择变量(Lasso算法的优势

岭回归算法的操作代码

简单来说,岭回归算法相对于OLS算法只是增加了L2惩罚项,因此操作步骤与OLS回归算法几乎一致。

(1)导入模块并加载数据

(2)指定特征变量和响应变量

在岭回归算法中,我们一样使用OLS中演示的例子。

(3)划分训练集和测试集

在示例中,我们将训练集和测试集默认为3:1,同时为了方便复现,随机状态random_state我们设置成0(实际上设置成任何整数都可行)。

(4)使用训练集训练模型

在使用岭回归算法时,我们需要设定调节参数的取值,即λ值的大小。在示例中,我们暂时将超参数设定为2,然后使用训练集数据进行模型训练。最后输出岭回归的测试性能得分、系数估计值和常数项。

(5)评估模型预测性能

与OLS算法类似,岭回归算法同样通过MSE或RMSE来判断训练模型的测试性能。

(6)调整参数选择最优模型

岭回归算法的调参过程与OLS算法类型,目的是获得MSE或RMSE最小的预测模型。在岭回归算法中,我们主要通过调整调节参数λ。一般来说,我们会根据个人研究的需求设置一系列可能取值的列表,然后观察每一个取值对应的MSE或RMS的变化和数值大小,从而选择最优模型。

Lasso回归算法

在面对高维数据时,我们会想在大量的特征变量中筛选出那些最能解释响应变量的特征变量。这一需求催生出了Lasso(Least Absolute Shrinkage and Selection Operator)回归算法。

Lasso回归算法的基本原理

(1)Lasso回归算法的原理

在总论的正则化部分我们指出,Lasso回归算法同样也是在OLS回归算法的基础上加入惩罚项。但与岭回归算法不同,Lasso回归中不使用L2范数惩罚项,而是变更成L1范数惩罚项:

(20)f=i(yiXiTβ)2+λi=1p|βj|

等式右边第二项是对所有待估计系数β求绝对值和(L1范数惩罚项)乘上一个调节参数λ。其中,调节参数λ0,当λ=0时,岭回归算法会回退到OLS回归算法。

根据链式法则,我们对L1范数惩罚项进行求导:

(21)βj|βj|={1,βj>01,βj<0不可导,βj=0

因此,目标函数在βj=0处不可微,只能使用梯度下降法进行求解。正是因为不可微性使得Lasso估计产生稀疏解,导致一些系数为0,从而实现变量选择。

为了更直观理解,我们从几何图形的角度展示Lasso回归算法挑选变量的功能。我们将公式20等价成:

(22)mini=1n(yiXβ^)2s. t.|βj|t

在二维空间下,约束条件变为|β1|+|β2|=t,即一个以原点为中心,边长为t2+t2=2t的正方形。

残差平方和的等值线几何图形依然是个椭圆形。

Lasso回归几何图形

从图中我们可以更直观的理解,如果要在正方形组成的可行解中将残差平方和最小化,那么最优解一定产生于正方形顶点与椭圆形曲线的交点,即Lasso回归的系数估计值。

在图中的情况下,β1=0,因此可以筛除变量x1。基于此,Lasso回归算法能够通过筛选对模型没有帮助的变量,以提高预测性能。

(2)Lasso回归算法的优缺点

Lasso回归算法相较于OLS回归算法和岭回归算法有一些优点:

特征选择可解释性强能够处理大规模模型数据稳健性强可以与其他算法相结合

当然,Lasso回归算法也存在一些缺点:

参数调节只适用于线性关系估计系数的偏向注意力不平衡

Lasso回归算法的操作代码

与岭回归算法一样,Lasso回归也有六个操作步骤:

(1)导入模块和加载数据

(2)指定特征变量和响应变量

(3)划分训练集和测试集

(4)使用训练集训练模型

(5)评估模型预测性能

(6)调整参数选择最优模型

算法调参

在机器学习中,为了寻找最优模型,我们需要选择最优参数。一般来说,机器学习的常见调参方式包括验证集法和交叉验证法。

验证集法

验证集法就是我们前边提及的,将样本数据分为训练集和测试集。该方法简单易懂、节约开支,但同时存在数据利用率低等缺点。并且,如果面对的未知数据是训练集中未出现过的,该模型的预测性能将会严重降低。

交叉验证法

交叉验证法的基本思想非常简单,通过重复使用数据实现模型稳定:把给定的数据进行切分,将切分的数据集组合成训练集和测试集,并在此基础上进行反复训练、测试和模型选择

机器学习中会大量使用K折交叉检验来度量测试误差,以K=10,10折交叉验证法为例:

步骤一、将样本中数据随机进行10等分(形成大致相等的10个子集

步骤二、将其中1个子集作为验证集(测试集),其余9个子集都作为训练集。进行模型的训练、评估、验证预测并计算MSE和RMSE。

步骤三、重复步骤二10次,直到每个子集都被作为验证集

步骤四、将所有验证集的MSE进行平均,即“交叉验证误差”(CVE)作为对测试误差的估计。

K折交叉检验的优点在于减小了验证集法的随机性和波动性,增加了模型评估的稳定性和准确性,让所有数据都有机会进入训练集。除了K折交叉检验法外,在样本量较小时还可使用留一交叉检验法,当然,其本质依旧是k=n的n折交叉检验法。其中,n为样本容量。换言之,将样本数据等分为n折,每折仅包含一个样本,因此不在具有随机性。

岭回归和Lasso回归的调参

在岭回归和Lasso回归算法中,当λ=0时,算法会退化为OLS回归算法;当λ时,估计参数β会趋于0。因此,最优λ会分布在[0,λmax]中。由于交叉检验法考量的是MSE,而MSE是凸函数,即:

(23)MSE(β)=1ni=1n(yiXiTβ)2(24)MSE(β)=1nyXβ22

MSE是个二次函数。此外,L1范数惩罚项和L2范数惩罚项均为凸函数。因此,[0,λmax]中,必然会有一点使得CV(λ)达到最小值,此点就是最优超参λ

算法调参的操作代码

我们将介绍几种算法调参的具体操作步骤。

循环寻找最优超参

(1)导入可能用到的模块,并加载数据

(2)先使用默认超参,观察模型的预测性能

(3)设置一系列备选的超参集,然后通过循环的方式计算每个超参对应的预测性能

(4)将每个参数对应的预测解出,并可视化

交叉验证选择超参

(1)导入可能用到的模块和数据集,采用10折交叉验证法,并设置一组备选的超参集(初始为0.01、最终为100、一共包含100个数的等比数列

(2)采用10折验证法,在备选超参中选择最优参数

重要特征选择

(1)导入可能用到的模块并加载数据集

(2)采用10折交叉验证,并设置一组备选的超参集(初始为0.01、最终为100、一共包含100个数的等比数列

(3)交叉验证,在备选超参中选择最优参数

(4)查看模型最终选择和剔除了几个特征变量

(5)通过画图展示各变量的重要程度


经典分类算法

分类算法是一种用于将数据分为不同类别或标签的算法。其中,机器学习的分类算法可分为有监督和无监督。在总论部分我们提到,有监督机器学习分类算法是指,在训练过程,使用带有标签的数据样本进行学习,每个数据样本都有一个已知的标签或类别,例如“是”或“否”,“好”或“坏”。有监督学习的目的就是通过学习数据样本与标签之间的关系,建立预测新数据样本标签的模型,常见的算法包括逻辑回归、决策树、随机森林、支持向量机等。无监督机器学习算法则试图在没有明确指导的情况下,自动对数据进行分类或聚类,常见的无监督学习算法包括主成分分析、聚类分析等。无监督学习的优点在于能够在没有标签的情况下探索数据的内在结构,有助于对数据进行理解和预处理,同时,无监督学习的结果依赖于人的解释。

举个直观的应用场景。

例如,我们需要根据政府留言板来判断人们对政府的评价。 若留言数量不多,我们可以人工识别;但当留言数量超过10万甚至100万条时,人工识别费时费力。 为此,我们可以借助有监督学习算法,先从100万条留言中随机抽取1000条,手动打上标签(“好政府”或“坏政府”),再根据训练数据特征和标签之间的关系建立模型,最后让机器帮我们将剩余的99.9万条留言都打上标签。

无监督学习则是我们让机器自己根据一定算法寻找特征之间的联系。

例如,我们不知道留言板中的留言都讨论哪些话题。为此,我们可以采用LDA主题模型,通过词汇概率对留言主题进行推测。

在本章节中,我们主要介绍几种常用的有监督机器学习算法,而无监督机器学习算法则会在后续章节中详细介绍。

K临近算法

K临近算法的基本原理

(1)K临近算法的原理

K临近算法(K-Nearnest Neighbors,KNN)的核心思想正如其名——近朱者赤,近墨者黑

涛声依旧和学猫叫
涛声依旧

举个生活中的例子。

不同时代的音乐风格差异很大,假如我们知道《涛声依旧》是1990年代的流行歌,而《学猫叫》是2020年代的。当我们听到《再回首》时,会下意识认为它更贴近《涛声依旧》而非《学猫叫》,从而将其归类为90年代流行歌曲。

K临近算法便是根据未知样本和训练样本之间的距离,预测分类。具体步骤如下:

第一步,收集包含已知类别标签的训练数据集

第二步,选择K值。K值是KNN算法的一个超参数,表示在分类时要考虑多少个最临近的样本。

第三步,计算距离。对于未知类别的新数据样本,在特征空间中计算其与训练数据集中每个样本之间的距离。常用的距离度量方法包括欧氏距离、曼哈顿距离、切比雪夫距离等。

第四步,确定最近邻。最近邻是指,在特征空间中距离目标样本最接近的样本点。

第五步,投票选择类别。根据K个最近邻的标签,投票决定新样本的类别。

(2)计算距离的选择

在不确定距离对结果影响的情况下,我们常用闵可夫斯基距离

(25)d(x1,x2)=(i=1m|x1ix2i|p)1p

p是闵可夫斯基指数,决定了距离的计算公式。

p=1时,变成曼哈顿距离

(26)d(x1,x2)=i=1m|x1ix2i|

p=2时,变成欧几里德距离(欧氏距离

(27)d(x1,x2)=i=1m(x1ix2i)2

p时,变成切比雪夫距离

(28)d(x1,x2)=mani|x1ix2i|

除此之外,在遇到文本型数据时会使用余弦相似度cos(θ)=x·y||x||||y||。在后续章节我们会进行更为详细的叙述。

总之,我们在使用KNN时需要依据应用场景,选择合适的距离公式。

p对应距离特点
p=1曼哈顿距离适用于高维稀疏数据
p=2欧氏距离适用于大多数情况
p切比雪夫距离只考虑最大坐标差

(3)KNN操作注意事项和优缺点

在操作过程中,我们需要关注:

KNN的不同取值

第一、K值的选择。如图片所示,当K值取3时,绿点的预测结果为红;而K值取5时,则为蓝。换言之,K值的选取对结果影响很大。当采用最临近法(K值为1)时,偏差为0但方差很大,此时决策边界很不规则,导致过拟合;当K值取非常大时,决策边界过于光滑,无法捕捉数据中的信号,使得预测性能下降,导致欠拟合。因此,与经典回归算法的λ一样,我们需要通过交叉验证或网格搜索(穷举)进行调参来选择合适的K值。一般来说,K值取一个较小的数值,3-5较为合适。

第二、选择合适的距离度量方式

第三、数据归一化。在使用KNN算法之前,通常需要对数据进行归一化,以避免某些特征对距离的计算产生过大影响。

第四、处理样本不平衡问题。当某些类别的数量较少时,需要考虑是否采取加权KNN算法,赋予不同的邻居样本不同权重。

诚然,KNN算法简单直观,但其依旧存在一些应用局限:

第一、KNN是懒惰学习算法。在KNN算法中,模型并不进行显式学习,而是将所有训练数据存储起来,直到需要预测时才根据距离计算以找到最接近的k个样本,进行投票或加权平均。

第二、KNN在高维空间很难找到邻居,会遇到“维度灾难”。因此,KNN算法要求样本容量n必须远大于特征向量的维度p。

第三、KNN对噪音变量不稳健。KNN算法无法区别对待对预测毫无关系的噪音变量,这会导致估计效率的降低。

K临近算法的操作代码

在示例中,我们会用到sklearn模块自带的鸢尾花分类数据。该数据包含150个样本,分为3类,每一类50个数据,每个数据包含4个特征,通过花萼长度、花萼宽度、花瓣长度、花瓣宽度来预测鸢尾花属于哪个种类(Setosa,Versicolor,Virginica)。我们会先导入数据,然后通过手动编写代码来实现K临近分类算法(帮助理解KNN如何实现),最后我们使用sklearn模块自带的KNN分类器实现分类。

加载数据和可能用到的模块

手动实现KNN算法

(1)进行数据可视化

将Y=0的点标记为空心点,Y=1的点标记为实心点。横坐标为花萼长度,纵坐标为花萼宽度。我们随机标记某一点(5.6,3.2),之后判断它属于哪个颜色。

(2)计算预测点到其他所有点的距离

在示例中,我们选择欧氏距离,计算预测点(x_1)到其他所有点的距离。

(3)选择K值,确认最近邻并投票选择类别

在示例中,我们暂时将K取值为6,即根据预测点的6个最临近样本确定其颜色。

使用KNN分类器实现分类算法

(1)加载数据导入可能用到的模块,并划分训练集和测试集

(2)建立KNeighborsClassifier分类器并调用fit方法进行训练,最后调用predict方法使用模型预测并输出分类准确率

(3)进行调参

与岭回归算法和Lasso回归算法类似,K临近算法同样需要调整超参数来实现最优模型。对机器学习而言,参数可分为模型参数和超参数。其中,KNN没有模型参数,因此我们需要调整两个超参数——K值权重

在调参中,我们使用sklearn库中自带的digits数据集。这是一个经典的手写数据子图数据集,属于典型的分类问题。在这个数据集中包含了8×8像素的手写数字图像,每个图像都是一个数字(0到9)。即,每个图像由64个特征组成,每个图像都对应一个数字标签,一共10个类别。

朴素贝叶斯算法

朴素贝叶斯算法的基本原理

(1)朴素贝叶斯算法的原理

朴素贝叶斯算法(Naive Bayes,NB)是一种基于概率统计的简单高效的机器学习分类器,基于贝叶斯定理和特征条件独立性假设,用于解决分类问题。朴素贝叶斯算法的核心思想可以简单概括为:倒推,即在给定一组特征的情况下,根据已知类别的数据计算每一个类别的后验概率,然后选择具有最大后验概率的类别作为预测结果。

后验概率Posterior Probability),是指某件事已经发生,计算事情发生是由某个因素引起的概率;先验概率Prior Probability),是指根据以往经验和分析,在实验或采样前就可以得到的概率。

举个例子。

假如发生了凶杀案,需要我们找到凶手。 此时我们可以根据过往的案子中“有类似情况时,嫌疑人通常是谁”,从而推断凶手,这个过程就是朴素贝叶斯。

当然,朴素贝叶斯是个被美化的翻译。“朴素”原词是“navie”,即天真的。朴素贝叶斯算法之所以“天真”,是其假定特征之间相互独立,即在给定类别的情况下,特征之间没有关联性(现实中几乎不存在完全相互独立的特征,所以这种算法其实是十分“天真”的设定)。但这样做的好处在于,能够使计算后的概率更加简化,从而提高计算效率。

(2)数学描述

设定输入空间XRnn维向量的集合,输出空间维类标记集合Y=c1,,c2,...,ci,...,ck,输入特征向量xX,输出空间分类标记yY。训练集数据T=(x1,y1),(x2,y2),...,(xn,yn)P(X,Y)独立同分布。其条件独立性为:

(29)P(X=x|Y=ci)=P(X(1)=x(1),...,X(n)=xn|Y=ci)(30)=j=1nP(Xj=xj|Y=ci)

朴素贝叶斯使用后验概率:

(31)P(Y=ci|X=x)=P(Y=ci,X=x)P(X=x)(32)=P(X=x|Y=ci)P(Y=ci)P(X=x)(33)=P(X=x|Y=ci)P(Y=ci)iP(X=x|Y=ci)P(Y=ci)(34)=P(Y=ci)jP(Xj=xj|Y=ci)iP(Y=ci)jP(Xj=xj|Y=ci)

其中,P(Y=ci)是先验概率,我们在分析之前需要先假设事件的概率分布,主要包括高斯分布(应用于连续数据)、多项式分布(应用于计数数据)、伯努利分布(应用于二分类数据)。

此外,因为朴素贝叶的“概率连乘”具有“一票否决”的特点,所有我们有时还需要进行拉普拉斯修正,即加一平滑。我们假设,一个随机变量X中,存在多个取值可能x1,x2,...,xi。计算特征条件概率:

(35)P(xi|Y=cj)=count(xi,cj)count(cj)

其中,count(xi,cj)是特征xi在类别cj中出现的次数,count(cj)是类别cj中的总样本数。如果xicj中从未出现过,count(xi,cj)=0,则后续概率都会为零。为了避免计算问题,我们加上拉普拉斯修正:

(36)P(xi|Y=cj)=count(xi,cj)+1count(cj)+k

其中,1是计数上的常数,表示我们假设每个事件至少出现1次;k是特征空间的大小。继而避免了概率为0的情况。

举个现实中的例子。

可乐与雪碧

我们在超市会看见非常多饮料,每种饮料都包含两个特征:含糖和含气。同时,我们知道可乐和雪碧含糖与含气的情况。现在,我们看到一款甜味气泡饮料,我们需要判断它是可乐还是雪碧。 首先,算法会计算先验概率。比如,可乐的市场占比是60%,雪碧是40%; 然后计算含糖和含气的可乐和雪碧的概率。假设含糖的可乐占市场70%,含气占80%;雪碧含糖占60%,含气占90%; 最后我们根据朴素贝叶斯计算新产品是可乐还是雪碧的概率。

可乐的概率:70%×80%×60%=33.6%,雪碧的概率:60%×90%×40%=21.6%。因此,朴素贝叶斯算法会预测这个新产品是可乐。

朴素贝叶斯算法的操作代码

在示例中,我们同样采用sklearn模块自带的鸢尾花数据集。基于不同的分布,朴素贝叶斯算法大致有三类:高斯朴素贝叶斯(Gaussian Naive Bayes)、多项式分布朴素贝叶斯(Multinomial Naive Bayes)、伯努利朴素贝叶斯(Bernoulli Naive Bayes)。

(1)高斯朴素贝叶斯

高斯朴素贝叶斯常用到的参数包括:

var_smooth,用于调整方差平滑的参数。它是一个非常小的常数,目的是避免某些特征的方差为零。该值越小,模型对小方差的特征越敏感;越大,模型对方差小的特征容忍度越高。一般默认为1e-9

priors,用于指定每个类的先验概率,一般默认None

fit_prior,是否学习分类的先验概率,一般默认True。如果设置为True,模型会根据训练数据自动估算类别的先验概率;如果设置为False,则先验概率由priors参数给定(如果priors=None则使用均匀分布)。

(2)伯努利朴素贝叶斯

伯努利朴素贝叶斯的操作过程与高斯朴素贝叶斯基本一致,只是参数会略微不同。

alpha,平滑参数,防止零概率问题,默认值为1,即拉普拉斯平滑。通常通过交叉验证来选择最佳的alpha值。较大的alpha值通常会增加平滑程度,从而降低模型的复杂度。

fit_prior,如果为True,则模型会根据训练数据自动计算各类别的先验概率;如果为False,则假设所有类别的先验概率是相等的(如果数据集类别分布不均,可以尝试将其设置为False,使得每个类别的先验概率相等,从而改善不均衡分类的效果)。默认值为True

class_prior,手动指定各类别的先验概率,覆盖fit_prior参数的效果。默认值:None,表示根据训练数据自动计算(例如,在鸢尾花示例中,可以指定三种类别的先验概率分别为[0.2, 0.4, 0.4])。

(3)多项式朴素贝叶斯

多项式朴素贝叶斯的参数主要包括:

alpha,平滑参数。如果设置为1.0,则表示进行拉普拉斯平滑。alpha是浮点型数据,值越大,平滑效果越强;如果设置为0,则不进行平滑。默认值为1.0。

fit_prior,是否使用类的先验概率。如果为True,则模型会根据训练数据估算每个类的先验概率。如果为False,则假定每个类的先验概率是相同的。fit_prior是布尔型数据,默认值为True

class_prior是一个数组,表示每个类别的先验概率。它的长度为类别数n_classes,每个元素是一个类别的先验概率。如果这个参数为None默认值),模型会自动根据训练数据计算每个类别的先验概率。

binarize用于二值化输入数据的阈值。如果特征的值大于该阈值,则该特征会被视为1,否则视为0。此参数在处理布尔特征时非常有用(例如,binarize=0)。

总的来说,高斯朴素贝叶斯、伯努利朴素贝叶斯、多项式朴素贝叶斯算法各有不同,需要根据实际的应用场景和数据情况进行选择。

特点高斯朴素贝叶斯伯努利朴素贝叶斯多项式朴素贝叶斯
适用场景特征是连续值,符合高斯(正态)分布特征是二值化的(即每个特征的值是0或1特征是计数数据或离散值,适用于文本分类等计数特征的数据
假设特征分布假设特征的分布是高斯分布假设每个特征的值独立且服从伯努利分布(0或1假设每个特征的值符合多项式分布(适合计数数据
特征类型适合连续特征适合二元(0/1)特征适合计数特征(词频
常见应用生物学数据、股票市场预测文本分类中每个特征是否出现文本分类、情感分析、推荐系统等
整体优点计算效率高,简单易实现适合分类中有二进制特征的情况适用于大规模的离散数据集,尤其是文本分类任务

决策树算法

决策树算法的基本原理

(1)决策树算法的原理

本质上,决策树也是一种临近方法,可视为“自适应临近法”(Adaptive Nearest Neighbor)。但与KNN不同的是,决策树(Decision Tree,DT)考虑了y的信息。

决策树

如图片所示,DT是一种基于属性结构的机器学习算法。从根节点开始,根据特定特征逐步划分,形成一系列决策节点,最终达到叶节点,从而实现对新数据的分类。

举个直观的例子。

我们在生病时会出现许多症状。在就诊过程中,医生为了知道我们究竟得的什么病,会对我们逐一询问。 哪里不舒服?什么时候不舒服有没有吃什么不干净的东西有没有拉肚子

在这个过程中,每一个问题都对应一个特征变量的划分,可能需要经过问多个问题(多次分裂)才能得到最后的判断(叶子节点)。

医生是如何决定先问什么问题,后问什么问题,什么时候停止继续发问而做出病情判断的?这个逻辑构成了决策树的规则。

决策树医生问诊
基于特征划分数据基于病症筛选疾病
逐步分裂节点逐步询问病情
叶子节点(分类或回归诊断明确或需要进一步检查
规则固定,基于数据训练结合经验、直觉和背景知识

参照这样的话语体系,构建决策树的步骤大致如下:

步骤一、将所有数据看成一个节点,进入步骤二

步骤二、从所有的数据特征中挑选一个数据特征分割节点,进入步骤三

步骤三、生成若干子节点,判断每一个子节点,如果满足停止分裂的条件,进入步骤四;否则退回到步骤二

步骤四、设置该节点为叶子结点,其输出的结果为该节点数量占比最大的类别

因此,决策树生成的关键在于:第一,如何进行特征选择;第二,数据如何分割(离散性);第三,什么时候停止分裂。

在分裂特征上,我们理应希望找到一个属性刚好能够将不同的类别分开。通常,特征选择的准则是信息增益(Information Gain,IG信息增益率(Information Gain Ratio,IGR。为此,我们需要理解何为信息熵。信息熵是信息量大小的度量,表示随机变量不确定的度量。具体而言,事件xi的信息量H(xi)可以度量为:

(37)H(xi)=i=1nP(xi)log2P(xi)

其中,P(xi)表示事件xi发生的概率,log2表示信息以比特(bit)为单位(以二进制为单位的原因是高效与普及),信息熵越大,随机不确定越大。

例如,一个均质硬币的信息熵为:i=1212log212=log22=1;一个六面均匀的骰子信息熵为:i=1616log216=log26=ln6ln22.58

信息增益表示得知特征X的信息而使得分类Y的信息不确定性减少的程度,反映了通过某一特征的划分,信息熵的减少程度。信息增益越大,说明这个特征越能有效地减少不确定性,从而帮助做出更好的分类。假如,数据集D的不确定信息熵为H(D),在得知特征A后,数据集D会根据特征A的不同取值被划分成多个子集,信息熵变为条件熵:

(38)H(D|A)=vvalues(A)|Dv||D|H(Dv)

其中,values(A)表示特征A的所有可能取值集合;Dv表示特征A取某个特定值v时,数据集D被划分出的子集;|Dv||D|是每个子集的权重,即子集Dv占数据集D的比例。

举个现实中的例子。

我们有数据集D,特征A是天气(取值为“晴天”、“阴天”、“雨天”),我们的目标是计算条件熵(是否出去打球)。

天气打球
晴天
晴天
晴天
阴天
雨天
雨天
雨天

此时,每个子集的信息熵为:

(39)H(D)=(23log223+13log213)=0.918(40)H(D)=log21=0(41)H(D)=(13log1+13log1+13log1)=0

从而,条件熵为:

(42)H(D|A)=37×0.918+17×0+37×0=0.393

信息增益为:

(43)g(D,A)=H(D)H(D|A)(44)=(37log237+47log247)0.393(45)=0.9850.393(46)=0.592

信息增益率(信息增益比)是信息增益的一个改进版本,主要用于解决信息增益在选择特征时,偏向于选择取值较多的特征的问题。特征取值较多时,信息增益通常较大(比如,城市这种可能有几十甚至几百取值的特征,其信息增益本就比性别这种二值特征更大。因此以城市作为分裂特征会得到更多信息增益,但这并意味着城市更有意义),而通过信息增益率的计算,可以避免这种倾向。= ,即:

(47)gR(D,A)=g(D,A)HA(D)(48)HA(D)=i=1n|Di||D|log2|Di||D|

其中,n是特征A取值的个数。我们还是以天气与打球的例子展开。

特征“天气”的熵(固有值)为:

(49)H(A)=(37log237+17+log217+37log237)=1.448

所以,信息增益率为0.5921.448=0.4088

除了信息熵外,我们也可以使用基尼系数表征样本的纯度,即基尼不纯度(Gini Impurity)。其公式如下:

(50)Gini=1i=1npi2

其中,pi为事件发生概率。

我们在选择属性后,决策树根据属性进行分裂。分裂属性的数据类型分为离散与连续两种。对于离散型数据,可以按照属性值分裂,每个属性值对应一个分裂节点;对于连续型数据,一般的做法是对数据按照属性排序,再将数据分成若干区间,每个区间对应一个节点,若数据的属性值落入某一区间,则该数据就属于其对应的节点(例如,将1-100岁进行分割[0,18]、[18,25]、[25,40]、[40,60]…)。同时,决策树也不可能无限增长,总会有停止分裂的时候,最极端的情况是当节点分裂到只剩下一个数据点时自动停止分裂,从而导致过拟合。决策树停止分裂的常见条件(我们在决策树中需要调整的超参数)包括:

第一、最小节点数。当节点的数据量少于一个指定数值时,将不在继续分裂。

第二、熵或基尼值小于阈值。数据纯度相对较大时,节点可以不在分裂。

第三、决策树的深度达到指定条件。节点深度可以理解成决策树根节点与节点之间的距离。根节点的深度定义为1,根节点后面以及的子节点深度为2,以此类推。当深度达到一定上限时,停止分裂。

(2)决策树的剪枝

对于任意子树TTmax,我们将其“复杂性”定义为子树T的最终节点数,计作[T]。为了避免过拟合,我们当然希望降低决策树的复杂程度。仿照回归算法,我们也可以对决策树的复杂程度进行惩罚:

(51)minTR(T)+λ[T]

其中,Tmax是最大决策树,即在没有任何限制下,决策树的完全结构。R(T)是树T的损失函数,表示模型的拟合度(例如,分类问题中的误差或回归问题中的均方误差)。λ是调节参数,用来平衡损失函数和复杂度之间的权重。较大的λ会更强烈地惩罚树的复杂性,促使模型更简洁,避免过拟合;较小的λ则允许更复杂的树结构。[T]是树T的复杂度,通常是树的叶子节点数量。增加叶子节点数会增加树的复杂度,正则化项λ[T]就是为了抑制这一点。

这个正则化的过程在决策树中又被称作剪枝(Pruing),即在构建完决策树后,通过删除一些不必要的节点或子树来减少模型的复杂性,从而提升其在未知数据上的泛化能力。剪枝通常分为两个类型:

前剪枝:在构建决策树时,提前停止分裂过程。当某个节点的分裂不再带来足够的信息增益,或者分裂后得到的子节点数量过少时,就停止分裂。这相当于限制树的最大深度或节点数。(例如,限制树的最大深度、限制叶子结点的最小样本数、最小信息增益

后剪枝:后剪枝是在决策树构建完成后,对树进行修剪,删除一些不必要的分支。后剪枝方法:首先构建一棵完整的决策树,然后从底到顶地考虑每个子树。如果去掉某个子树的效果不会导致过多的性能下降,就将这个子树删除,替换成一个叶节点。(例如,最小化验证集误差、代价复杂度剪枝

(3)回归树

除了分类外,决策树也可以应用到回归问题上,即回归树(Regression Tree,RT)。在回归树中,每一个叶子都输出一个预测值,预测值一般是该叶子所含训练集元素的均值。对于回归问题,其响应变量y为连续变量,因此回归树一般以MSE作为结点的分裂规则。在进行结点分裂时,我们选择能够最大程度降低MSE的划分点,即两个子节点(左和右)的残差平方和最小。

举个生活中的例子。

我们需要根据房屋面积预测房子价格。数据如下:

面积(平方米)价格(万元)
5080
6090
70100
80110
90120
100130

我们计算整体MSE:

(52)y¯=80+90+100+110+120+1306=105(53)MSE=(801052)+...+(130105)26291.67

接着计算不同分裂点的MSE:

基于最大信息增益(MSE75=225),我们选择75平米作为最佳分裂点。从而生成回归树:

因此,当房屋面积75m2时,预测价格为90万元;房屋面积75m2时,预测价格为120万元。

当然,回归树也可以使用惩罚项进行剪枝:

(54)minT=m=1[T]xiRm(yiy^Rm)2+λ[T]

(4)决策树算法的几个模式

一般来说,决策树可分为ID3、C4.5、CART树。

ID3(Iterative Dichotomiser 3)建立在奥卡姆剃刀定律(若无必要,勿增实体)的基础上:小型树优于大型树。ID3的核心思想是以信息增益来度量特征选择,选择信息增益最大的特征进行分裂,该算法采用自上而下的贪婪算法(局部最优、不回溯、希望全局最优)构建决策树。

C4.5是ID3的改良版,其核心思想是使用信息增益率来划分特征,从而解决ID3偏向取值较多特征的问题。同时,相较于ID3,C4.5引入了悲观剪枝(一种特定的后剪枝方法,通过对每个子树的误差估计,保守地判断是否进行剪枝)。

CART(Classification and Regression Tree)的核心思想是,面对不同的任务选择不同的划分规则。对于分类任务,CART使用基尼系数作为划分标准;对于回归任务,CART使用MSE作为划分标准。在剪枝上,CART使用成本复杂度剪枝(Cost Complexity Pruning,后剪枝的一种方法)。具体而言,首先,CART会生成一颗完整的树;其次,从最复杂的树开始,计算每个节点的成本复杂度(Cost Complexity=misclassification error+α×number of terminal nodes其中misclassification error是分类错误率;number of terminal nodes是最终节点数;α是正则化参数,控制树的复杂度);再次,对每个节点进行评估,选择一个α值来最小化误差和复杂度的组合(CART会评估每个子树的剪枝后误差,如果剪枝后误差变化较小,则保留剪枝操作,如果剪枝后的误差显著增加,则该子树不会被剪枝);最后,确定最优的剪枝策略(通过交叉验证,CART会选择一个最佳的α值来平衡树的复杂度和误差。当α较大时,CART倾向于剪去更多的节点,使树变得更加简单;当α较小时,树的复杂度较高)。

总体而言,我们同样需要根据应用场景合理选择决策树的模式。

特性ID3C4.5CART
算法类型分类树分类树分类树/回归树
分裂标准信息增益信息增益率基尼不纯度/均方误差
处理连续值不能直接处理,需要离散化可以处理,基于阈值划分可以处理,基于回归方法划分
树的类型二叉树不一定是二叉树,允许多叉树二叉树
剪枝没有内建剪枝机制后剪枝后剪枝
节点选择选择最大信息增益的属性选择最大信息增益率的属性选择基尼不纯度或均方误差最小的属性
处理缺失值不处理通过概率或分裂策略处理通过不纯度的分布处理
树的复杂度控制没有直接的复杂度控制机制可以通过信息增益率控制复杂度通过剪枝和正则化参数控制复杂度
适用性主要用于分类问题主要用于分类问题适用于分类和回归问题

决策树算法的操作代码

在决策树的操作示例中,我们同样使用鸢尾花数据集。

(1)加载数据和可能用到的模块,划分训练集和测试集后进行模型三步走(声明分类器、训练模型、预测结果

(2)进行调参

为了防止过拟合问题,我们需要进行调参,主要包括:

方法代码作用
降低深度例如:max_depth=3限制树的最大深度,减少过拟合
预剪枝例如:min_samples_split=5, min_samples_leaf=2限制节点分裂,防止树过度生长
后剪枝例如:ccp_alpha=0.01先生成完整树,再剪枝,减少复杂度

此外,由于sklearn模块的默认决策树算法是CART,以基尼不纯度为分裂规则。想要换成ID3算法需要手动更改分裂标准,即criterion=entropy

对超参的选择上,常使用网络搜索(Grid Search,适用于参数范围较小)和随机搜索(Randomized Search,适用于参数范围较大)。

总的来说,我们同样需要根据具体的应用场景来选择超参。

特点网格搜索随机搜索
搜索方式穷举法,遍历所有可能的超参数组合随机选择超参数的组合进行测试
计算复杂度随着超参数数量和每个超参数可能值的增加,计算量迅速增大在超参数空间大的时候计算量较小,可以通过设置次数控制计算量
寻找最佳解的能力对于小空间的超参数,能够找到最优解在大空间中可能会找到接近最优的超参数
适用场景超参数空间较小,或者对精度要求很高超参数空间较大,或者计算资源有限时
优缺点精度高,但计算成本高;适合超参数少且范围小的情况计算成本低,速度快,能探索更广阔的空间,但不能保证找到最优解
代码GridSearchCVRandomizedSearchCV

支持向量机算法

支持向量机算法的基本原理

(1)支持向量机算法的原理

支持向量机

正如图片展示,为了分割蓝点和绿点,我们可以找到无数条直线。但现实情况往往没有图中那么理想,有时蓝点和绿点是相互参杂的。假如我们想要的是一条能够最大限度将蓝点和绿点分开,并保证两边不会混进太多异色点,那么支持向量机(Support Vector Machine,SVM)就可以帮助我们找到这条线。

这只是二维平面的情况,如果是在高维数据中,支持向量机将不再是一条直线,而是一个“超平面”(超平面是一个比空间低一维度的对象,比如在二维空间中超平面是条直线;三维空间中,超平面是个二维平面),就像图片中所展示的那样。

超平面

当然,在进行分割时,我们一般只关心与距离超平面最接近的几个点,这些点就是“支持向量”。总的来说,支持向量机就是在一个数据中找到最佳分界线或者分界面的工具,它通过寻找最大化间隔来让不同类别的数据点尽量分开

(2)数学描述

在公式推导之前,我们需要先理解超平面与法向量(Normal Vecto,垂直于超平面的向量)之间的垂直关系。我们以二维空间为例。

在二维空间中,超平面是一条直线,即:

(55)w1x+w2y+b=0

在这里,法向量为(w1,w2)。我们以原点(0,0)出发,沿着法向量作一条直线,即:

(56)y=w2w1x

此时,直线斜率为w2w1。根据公式55可知,超平面的斜率为w1w2。两条直线的斜率乘积为w1w2×w2w1=1,说明两条直线相互垂直(例如,y=xy=x相互垂直),故法向量与超平面始终垂直。

假设现在我们知道一点P(x1,y1),需要求点到超平面的距离。为此,我们需要在超平面上找到一点Q(x2,y2),使得PQ=(x1x2,y1y2)与超平面垂直,换言之PQ与法向量平行。为了计算PQ的长度,我们会将PQ投影到法向量上。根据公式:

(57)=|ab|||b||

其中,ab是点积ab=||a||×||b||cosθ||b||b的模长。由于PQ与法向量平行,因而cosθ=1,即ab=||a||×||b||。我们将数据带入公式,获得点P到超平面的距离:

(58)d=|w1(x1x2)+w2(y1y2)|w12+w22(59)=|w1x1+w2y1(w1x2+w2y2)|w12+w22(60)=|w1x1+w2y1+b|w12+w22(61)=|wP+b|w12+w22

举个直观的例子,我们假设在二维空间中,超平面为x=5即,x+0y5=0,所以法向量为(1,0)。此时,我们想知道点(1,1)到超平面的距离。带入公式d=|15|1=4。根据直观的判断,我们也知道点(1,1)到点(5,1)为4。

现在,我们将这个公式推广到多维空间中,便可求出多维空间某一点到超平面的距离。参照二维空间,多维空间的超平面公式为:

(62)wTx+b=0

其中,w是法向量,决定超平面方向;b是偏置项,决定超平面的位置;x是输入样本。对于空间中样本xi,其到超平面距离为:

(63)d=|wTxi+b|||w||

wTxi+b>0说明样本在超平面的一侧;wTxi+b<0说明样本在超平面的另一侧;wTxi+b=0说明在超平面上,此时d=0

最大间隔法

由于支持向量机考虑的是一个二分类问题,因而对于数据点(xi,yi)yi是类别,yi(+1,1),分类规则是yi(wTxi+b)1,表示所有数据点都在间隔边界外。为了简化计算,我们将wTxi+b定义为1,表示1个间隔(并非真实距离1)。根据支持向量机的对称性,两个支持向量的间隔为d=|2|||w||。换言之,这是一个关于||w||的函数。为了尽可能将数据分开,我们理应希望两个支持向量的间隔最大,即||w||尽可能小。在对间隔取平方后d2=4||w||2,4是常数,对结果并不会产生任何影响。因此,我们将找到最大化间隔的超平面问题转变成最小化法向量范数:

(64)minw,b12||w||2(65)s.t. yi(wTxi+b)1,i

由于常数并不会对最小化问题有产生任何影响,因此系数取12只是为了方便计算,即对12||w||2求导后会只剩下w

这是一个带有约束条件的凸优化问题(12||w||2是个凸函数,必定存在全局最优解),我们可以通过拉格朗日对偶进行求解。使用拉格朗日乘子法:

(66)L(w,b,a)=12||w||2i=1nαi[yi(wTxi+b)1]

其中,αi是拉格朗日乘子,必须满足KKT条件:αi0。通过对偶优化,目标是最小化w,b,并最大化α

w,b求偏导并令其为0:

(67)Lw=wi=1nαiyixi=0w=i=1nαiyixiLb=i=1nαiyi=0

w=i=1nαiyixi,带入L(w,b,a)

(68)L(α)=12||i=1nαiyixi||2i=1nαi[yi(wTxi+b)1](69)=12i=1nj=1nαiαjyiyjxiTxji=1nj=1nαiαjyiyjxiTxj+i=1nαi(70)=i=1nαi12i=1nj=1nαiαjyiyjxiTxj

因此,对偶问题为:

(71)maxi=1nαi12i=1nj=1nαiαjyiyjxiTxjs.t. i=1nαiyi=0ai0,i

这属于二次规划问题,可用SMO(Sequential Minimal Optimization)或梯度下降法求出最大α。求解后使用α计算wb

(72)w=i=1nαiyixib=ysi=1nαiyixixs

其中,w是所有支持向量的线性组合,xi是第i个样本的特征向量,yi是对应的标签(±1);偏位置b通过支持向量计算,(xs,ys)是空间中任意支持向量。

最终的分类函数为:

(73)f(x)=sign(wTx+b)

以上是基于线性可分情况下使用硬间隔最大优化法。当线性不可分时,我们需要使用软间隔最大化法和核技巧。

硬间隔SVM要求数据严格线性可分,但现实中的数据经常存在噪音或轻微重叠问题,软间隔就是允许部分样本能够被错误的分类。软间隔最大化法的的核心是引入松弛变量(Slack Variableξi0,表示对每个样本允许的误差,并添加惩罚系数C控制对误分类的容忍度。因而,原始问题就转变成:

(74)minw,b,ξ12||w||2+Ci=1nξi(75)s.t. yi(wTxi+b)1ξi,i(76)ξi0,i 

其中,C越大,则对误分类的惩罚越强(间隔越“硬”);C越小,允许更多样本违反间隔(间隔越“软”)。

核技巧(Kernel Trick)是在数据不线性可分时,将输入空间映射到高维特征空间,使其在新空间中可分。

我们借助几何图形理解。

核技巧

假设我们需要分割红点与黄点,最合理的方式当然如图中绿色曲线一样,画一个圆。但这个圆是非线形的,是一个线性不可分情况。我们希望能够做到线性可分,只能将这个二维空间映射到三维空间中。当我们进一步增加特征后,这个二维图像在三维空间中能够找到一个平面,将其变为线性可分。

核函数K(xi,xj)是一个对称函数,可以直接计算映射后的内积ϕ(xi)Tϕ(xj),从而对偶问题中的内积替换成核函数:

(77)maxi=1nαi12i=1nj=1nαiαjyiyjK(xi,xj)

一般来说,常见的核函数有:线性核:K(xi,xj)=xiTxj、多项式核:K(xi,xj)=(xiTxj+c)d、高斯核:K(xi,xj)=exp(γ||xixj||2)、sigmoid核:K(xi,xj)=tanh(βxiTxj+θ)

使用核函数后,分类函数变为:

(78)f(x)=sign(i=1nαiyi(xi,x)+b)

支持向量机算法的操作代码

在支持向量机算法的示例中,我们同样使用鸢尾花数据。

(1)基本流程

参照之前的分类问题,我们加载数据并导入可能用到的模块后,进行三步法(划分训练集和测试集并对特征进行标准化、训练分类器、预测并计算准确率)。除此之外,为了方便后续的模型调参,我们选择绘制SVM的可视化结果。

(2)进行调参

由于SVM的硬间隔最大化法只能用于线性可分的情况,因此我们需要调整的超参数主要针对线性不可分而言的,包括:

C软间隔参数,控制着分类边界的松弛程度,影响误分类样本的惩罚,越大惩罚越严格。

kernel核函数类型。我们在核技巧部分提到,SVM中常见的核函数包括linear,线性核;poly,多项式核;rbf高斯核;sigmoid,sigmoid核。一般来说,线性可分时直接使用kerneal='linear';非线性问题常用kernel='rbf';有明显的高次关系使用kernel='poly'

核函数适用情况参数
线性核数据近似线性可分C
多项式核处理多项式特征关系degree(阶数),coef0(常数项),gamma
高斯核适用于大多数非线性数据gamma核宽度
sigmoid核类似于神经网络的激活函数gammacoef0

gamma控制单个样本对决策边界的影响范围,类似于回归中的核宽度(gamma越小,每个样本影响范围大,决策边界更平滑,泛化能力更强,但可能会欠拟合;gamma越大,每个样本影响范围小,边界更精细,可能过拟合)。一般推荐gamma='scale'默认),根据1/(n_features * X.var())自动计算;gamma='auto'1/n_features计算,一般不如scale

degree表示多项式的阶数,degree=2表示二次曲面,degree=3表示三次曲面,依此类推。

coef0是多项式核和sigmoid核的偏置项,控制高阶项对模型的影响。较大的coef0更强调高阶多项式特征。

class_weight用于处理类别不均衡的情况,给之加权。一般会默认class_weight=None,表示所有权重相同;class_weight='balanced',表示自动调整类别权重,使数据集的类别分布均衡。当然,当遇到样本类别非常不均时,也可手动赋权,例如class_weight={0: 1, 1: 2, 2: 5}

与决策树调参方法一样,SVM的调参也常用网格搜索与随机搜索。

总体来说,SVM的优点在于能够很好的适用高维数据,并在进行预测时仅使用支持向量,提高预测效率。但SVM是一个二分类算法,因此在进行多分类问题上,会将其变为多个是或否的问题,无法从概率的角度进行解释。

分类算法的评估

准确率和错误率

对于有监督学习的问题,我们一般用预测效果来评估其模型性能。具体来说,我们在分类问题上常用准确率(Accuracy)和错误率(Error Rate)。

准确率,即“正确预测的百分比”,我们只考虑样本数据的预测值与实际值:

(79)=i=1nI(y^i=yi)n

错误率又叫错分率,是指预测错误的样本数与全部样本的比例:

(80)=i=1nI(y^iyi)n

混淆矩阵、精准率、召回率、F1分数

混淆矩阵(Confusion Matrix)是一个表格,用于描述分类模型在不同类别上预测的结果。它展示了真实标签和预测标签之间的关系。

实际观测值
正例(Positives) 反例(Negatives)
预测值 正例(Positives) 真阳性(True Positives,TP) 假阳性(False Positives,FP)
反例(Negatives) 假阴性(False Negatives,FN) 真阴性(True Negatives,TN)

精准率(Precision)是指,模型预测为正例的样本中,实际为正例的比例:

(81)=TPTP+FP

召回率(Recall)是指,模型能够正确识别的正例占所有真实正例的比例:

(82)=TPTP+FN

F1分数(F1 Score)是精确率和召回率的调和平均值,综合考虑了模型的精确性和召回能力:

(83)F1分数=2××+

在生物医学中,我们有时也会考虑真阴率(又称为特异度,是指反例被正确分类的比例)和假阳率(1-特异度)。

(84)=TN(FP+TN)(85)=FPFP+TN

其中,TP是真阳性,模型正确预测为正类的样本数;TN是真阴性,模型正确预测为负类的样本数;FP是假阳性,模型错误预测为正类的样本数;FN是假阴性,模型错误预测为负类的样本数。

ROC曲线和AUC

ROC曲线(Receiver Operating Characteristic Curve)和AUC(Area Under the Curve)是评估分类模型性能的常用工具,尤其适用于不平衡数据集。

举个医学实验的例子。

假设我们有一个二分类问题,目标是预测某个疾病发生或未发生。我们的数据集包括多个特征(如患者的年龄、体重等),并且我们使用一个模型(例如逻辑回归)来进行预测。模型给出的输出是每个样本属于正类的概率,而不是直接的类别标签(如“0”或“1”)。

ROC曲线通过绘制召回率和假阳率来描述分类器性能的变化,通过不同的阈值设置,可以得到不同的召回率和假阳率,从而绘制出ROC曲线。

AUC是ROC曲线下的面积。AUC的值介于0到1之间,AUC越接近1,表示模型的表现越好;AUC为0.5表示模型没有辨别能力;接近0表示模型非常差。

我们以鸢尾花数据作为示例,使用逻辑回归算法计算ROC曲和绘制AUC。

从图中可以看到,使用ROC和AUC来评估多分类问题,会将每个类别重新布尔化,即将多个类别转换成是与否,之后重新计算ROC和AUC。ROC曲线越接近左上角,AUC越接近1,说明模型表现得越好。


自然语言处理

在KNN部分我们提到,距离的计算公式除了根据闵可夫斯基距离演化出的曼哈顿距离、欧氏距离和切比雪夫外,还有余弦相似度。当时我们提到,余弦相似度常用于计算文本距离。在社会科学中,我们往往会面临许多文本资料,如何对其进行分析成为了自然语言处理的任务。如今,NLP最常见的应用场景包括:情感与词语分析、市场预测、考量政策不确定性、行业动态分析以及衡量企业融资约束程度。

一般来说,计算机是无法识别文字的,我们所看到的内容都是一连串由0/1组成的矩阵。因此,进行自然语言处理的关键就是如何处理文本。主要包括4个步骤:

第一步,获取文本数据。获取文本数据的方式很多,例如网络爬虫、服务器API接口、公开数据集等。

第二步,将获取到的文本转换成数据矩阵,即将单词转换成向量。目前主流的方法包括:独热表示法(One-Hot Encoding)、词袋模型(Bag of Words,Bow)和词嵌入法(Word Embedding)。

独热表示法:每个词在向量中都有一个对应的唯一位置。如果词出现在文本中,对应位置是1,其他位置是0。换言之,独热编码并没有考虑词与词之间的关系,只表示出现与否。

词袋模型

词袋模型:把整篇文本看作一个单词集合(袋子),不考虑单词顺序,记录每个单词的词频。与独热表示法不同,它可以表示单词出现的次数,而不仅仅出现与否。

词嵌入模型

词嵌入法:词嵌入将高维、稀疏的离散表示转换为低维、密集的连续向量表示,让语义上相似的词具有相似的向量(如图片中通过t-SNE将单词从七维降至二维)。其核心是,出现在相似上下文中的单词应该具有相似的语义,因而可以通过一个词的上下文来理解含义。

举个例子。

文本1:猫猫在草坪上玩耍。 文本2:狗狗在草坪上玩耍。

在独热表示法中,构建的词汇表为[“猫”, “在”, “草坪”, “上”, “玩耍”, “狗”]。将文档转变成向量后:文本1[1, 1, 1, 1, 1, 0];文档2[0, 1, 1, 1, 1, 1]。每个分类出现为1,没出现为0。

在词袋模型中,构建的词汇表一样是[“猫”, “在”, “草坪”, “上”, “玩耍”, “狗”]。将文档转变成向量后:文本1[2, 1, 1, 1, 1, 0];文档2[0, 1, 1, 1, 1, 2]。记录了每个单词在文档中的出现次数。

在词嵌入法中,会将词语放在整个词语放在句子中,例如猫猫和狗狗所处的上下文是相似的,因此它们的词向量也十分接近。词嵌入是通过训练模型(如Word2Vec、GloVe、FastText等)获得的。每个词都会被映射为一个固定维度的向量。通过这些向量,可以捕捉词之间的相似性和语义信息。假如我们现在有一个已经训练好的词嵌入模型(例如,Word2Vec),我们将每个单词转变成向量。假设猫[0.5, 0.2, -0.1];狗[0.3, 0.4, -0.2];草坪[0.1, -0.2, 0.3];玩耍[0.6, 0.1, -0.4](在、上是停用词,不参与词嵌入)。因此,文本1:[0.5,0.2,0.1]+[0.1,0.2,0.3]+[0.6,0.1,0.4]3=[0.4,0.0333,0.0667];文本2:[0.3,0.4,0.2]+[0.1,0.2,0.3]+[0.6,0.1,0.4]3=[0.3333,0.1,0.1]

第三步,提取数据矩阵的信息。根据训练数据是否带有标签,文本分析可分为有监督学习与无监督学习两种方法。其中,无监督学习包括词典法(基于预先建立的词典或词汇表来处理文本数据。一般会先建立一个包含与特定领域相关的词语或短语,并标注情感极性——好、坏;之后对新的文本数据进行情感分析,遍历文本中的每个词汇,检查其是否在词典中,并获得其情感极性标注;最后根据词典中词语的情感极性,计算文本的总体情感得分,并判断情感倾向)和主题分类模型(LDA,一般采用词袋模型将每一篇文本都看成一个词频向量,从而将文本转变成数字信息。每篇文档代表了一些主题所构成的概率分布,而每个主题又代表了一些单词所构成的概率分布)。常见的有监督学习包括SVM、逻辑回归、随机森林、KNN等。

第四步,深度学习。深度学习作为机器学习的分支,通过构建深层的神经网络来学习和表示数据的复杂程度,常见的深度学习算法包括:卷积神经网络、循环神经网络、长短期记忆网络、生成对抗网络、自编码器、注意力机制、Transformer等。

分词

分词的基本原理

简单来说,中文的分词方法包括基于词典的分词、基于统计的机器学习算法分词、基于规则的分词以及结合多种方法的混合分词。其中,我们最常用的分词工具为jieba分词,其提供了三种分词模式,并能够让允许用户自定义一些停用词(例如,的地得这类没有意义的助词)和词典(比如,新时期中国特色社会主义这类特定词汇)。

分词模式说明适用场景示例(“我爱自然语言处理”
精确模式(默认精确切分,不会多切词,确保分词结果最合理文本分析、自然语言处理我爱 / 自然语言处理
全模式试图把所有可能的词都扫描出来,冗余度较高搜索引擎构建索引我 / 爱 / 自然 / 自然语言 / 语言 / 语言处理
搜索引擎模式在精确模式基础上,对长词再切分,增加召回率搜索引擎、信息检索我爱 / 自然语言 / 语言 / 语言处理

正如表格所示,同一句子在不同的分词模式下会获得皆然不同的结果,就像那个经典段子所写的“武汉市长江大桥”可以分为“武汉市,长江大桥”和“武汉市长,江大桥”。因此,选择何种模式需要根据应用场景和使用者对语句的理解。

分词的操作代码

接下来我们以2025年政府工作报告为例,展示NLP如何运作。

接下来我们调用jieba.posseg模块中的中文分词和词性标注功能。

为了使分词结果更符合预期,我们进行停用词处理并添加自定义词典。

总体而言,分词大致分为五个步骤:

第一步,加载需要用到的文本数据、停用词表和自定义词典

第二步,对文本进行预处理。使用正则表达式对文本进行清理,去除了不可见字符、特殊符号、多余空格以及标点符号,使得分词过程更加准确。

第三步,对文本进行分词。使用jieba.cut()将文本切分为词语。这一步是中文文本分词的核心。

第四步,过滤停用词。将分词结果中的停用词过滤掉,保留对分析有用的词汇。

第五步,输出结果。可以使用jieba.posseg.cut()进行词性标注,为每个词汇打上标签;通过Counter对分词后的词汇进行频率统计,找出高频词。

TF-IDF

TF-IDF的基本原理

阐述何为TF-IDF之前,我们举个简单的例子。

我们看中文期刊时,中国一定是高频词汇之一。但如果都以高频词汇来概括文章内容,会导致所有文章都是关于中国的,此时在进行分析将毫无意义。 但如果一个平时比较少见的词(比如,小猫),在文章中出现比较多时,那么这个词将比“中国”更能描述文章的特征。

因此,我们在分析文章内容时,不能只考虑词频(Term Frequency,TF),还需要考虑词语的权重,而这个权重叫做逆文档频率(Inverse Document Frequency,IDF)。IDF的大小与该词在文档中的常见程度成反比,通常情况下,某个词在很多文档中都出现,那么它就不太能区分文档的差异。我们将TF与IDF相乘后,便能得到TF-IDF值,值越大说明某个词对文章的重要程度越高。具体步骤如下:

步骤一,计算词频。词频表示某个词语在文档中出现的频率,计算公式为:

(86)(TF)=

步骤二,计算逆文档频率。逆文档频率表示某个词语在整个文档集中的重要性,如果一个词在文档中越常见,其越接近于0。IDF的计算公式为:

(87)(IDF)=log(+1)

步骤三,计算TF-IDF。TF-IDF是TF与IDF的乘积:

(88)TF-IDF=TF×IDF

举个例子。假设现在我们有三个文档:

文档1:我爱自然语言处理。 文档2:深度学习与自然语言处理很有趣。 文档3:深度学习是计算机视觉图像研究的重要工具。

此时,我们需要计算“自然语言处理”在文档1中的TF-IFD值。在文档1中,我们可以将句子分割成“我/爱/自然语言处理”,总词数为3。其中“自然语言处理”出现了1次,因此TF为1/30.3333;其次,“自然语言处理”在三个文档中出现了两次,因此IDF为log(3/3)=0。最终,“自然语言处理”在文档1中的TF-IDF为0.3333×0=0

TF-IDF的操作代码

我们仍然以这三个文档为例,借助gensim模块来展示NLP如何自动计算TF-IDF值。

当然,我们也可以在上述步骤中加入停词表和使用自定义字典以提高准确性。

文本相似度

文本相似度是衡量两个文档或多个文档之间相似程度的重要标准,是NLP中的重要概念。例如,我们想知道每年的政府工作文件是否有发生变化,哪些年份的变化程度更多,哪些年份更相似,我们就需要计算文档之间的相似度。

文本相似度的基本原理

我们在介绍KNN时提到,当涉及文本内容时,我们会使用余弦相似度作为文本相似的度量方法,其核心思想来源于映射。由于计算机无法识别文字,需要对文本进行向量化,因此我们假定文档a的向量为a(x1,y1),现在我们对其进行投影得到向量b(x2,y2)

余弦相似度

如图片所示,现在我们想知道向量ab在方向上有多相似,根据ab=||a||×||b||cosθ

(89)cosθ=i=1naibii=1nai2i=1nbi2

从而我们获得了一个只依赖于夹角θ的值。根据余弦函数的性质,cosθ的值在-1和1之间,表示两个向量的方向关系:1表示两个向量完全相同(夹角为0°);-1表示两个向量完全相反(夹角为180°);0表示两个向量无关(夹角为90°)。

举个例子,我们现在有两句话:

句子1:深度学习需要数学基础。 句子2:数学是深度学习的基础。

词表:[深度, 学习, 数学, 基础, 是, 需要]; TF-IDF向量(假设值):句子1[0.8, 0.6, 0.7, 0.5, 0, 0.3];句子2[0.7, 0.5, 0.9, 0.6, 0.2, 0]。

两句话的余弦相似度为:

(90)cosθ=0.8×0.7+0.6×0.5+0.7×0.9+0.5×0.6+0×0.2+0.3×00.82+0.62+0.72+0.52+02+0.32×0.72+0.52+0.92+0.62+0.22+02(91)=0.9476

总的来说,基于余弦相似度的文本相似度计算分四个步骤:

步骤一,进行中文分词

步骤二,求出两个词集的并集

步骤三,计算各自词集的词频并进行词频向量化

步骤四,带入向量计算模型从而求出文本相似度

一般来说,我们在进行文本分析时,会同时结合TF-IDF和余弦相似度。这是出于词语重要性和文档频率的考量,该做法能够降低常见词对相似度的影响,同时突出关键词对相似度的贡献。

文本相似度的操作代码

我们以历年政府工作报告为例,寻找每一年政府工作文件的相似程度,并从中找到文本相似程度最高的三篇文档。在方法上,我们分别使用TF-IDF+余弦相似度、Word2Vec+余弦相似度和BERT句向量+余弦相似度。

(1)TF-IDF+余弦相似度

该方法需要注意的是,通过BoW语料转换的TF-IDF权重向量只是一个稀疏向量(大部分元素是0,只存非零元素和索引),需要将其转变成密集向量从而进行余弦相似度计算。

(2)Word2Vec+余弦相似度

由于Word2Vec是词嵌入的方法之一,专门用于将单词转换为固定长度的向量,并且这些向量能够捕捉到单词之间的语义和上下文关系。因此,在计算平均词向量时我们需要对Word2Vec进行模型设定。在示例中,vector_size=100表示,每个单词会被表示为100维的向量;window=7表示,每个词考虑前后7个单词作为上下文来学习向量;min_count=3表示语料库中出现次数低于3的单词会被忽略。

(3)BERT句向量+余弦相似度

与传统NLP流程不同,BERT使用WordPiece进行词语分解,这是一种基于子词的分词方式,能够把一个单词切分成更小的字词。换言之,BERT会根据上下文对输入文本进行理解而无需事先分词。因此,在文本处理上,我们直接调用Transformer模型tokens = tokenizer.tokenize(doc),之后每个句子生成一个BERT句向量。return_tensors="pt"表示将输入转换为PyTorch张量;padding=True表示自动填充到固定长度(为了适应BERT的输入要求);truncation=True表示句子超过最大长度时截断;max_length=512表示上下文最大长度为512单词(BERT的最大输入长度)。最后,分批获得所有文档的句向量后将其转变成密集矩阵(batch_size=8表示每批处理8个文档,目的是减少计算时避免内存溢出)。

除此之外,我们可以通过绘制热力图,查看每个政府工作报告之间的相似程度及其变化。

综合来说,三种计算文本相似度的方法各有优劣。TF-IDF+余弦相似度的优点在于简单且计算量小,但无法考虑词序和上下文关系。Word2Vec+余弦相似度指一个折中的办法,相比于比TF-IDF+余弦相似度能够理解词语的语义相似性,但并不能理解句子之间的关系。 BERT句向量+余弦相似度使用上下文感知的深度学习模型,因此能够捉词语间复杂的语义和上下文关系,但同时,BERT模型计算资源消耗大,当处理海量数据时及其有赖于计算机的性能。因此,我们最好根据自己的需求选择适合的计算方法。

特性TF-IDF+余弦相似度Word2Vec+余弦相似度BERT句向量+余弦相似度
表示方法词频和逆文档频率的加权表示,每个单词是一个高维稀疏向量每个单词通过训练获得一个低维稠密向量,捕捉语义关系使用上下文感知的深度学习模型生成句子的稠密向量
优点简单直观,适用于短文本,计算效率高能捕捉词语的语义相似性,训练数据量大时效果较好高度语境敏感,能捕捉词语间复杂的语义和上下文关系
缺点无法考虑词序和上下文,忽视了语义层面只能捕捉单词级别的语义信息,句子层面的信息较弱计算资源消耗大,对长文本和大规模数据集有较高要求
处理长文本能力较弱,长文本需要拆分成多个片段进行处理处理长文本时需要切分词,且词向量无法处理句子整体能有效处理长文本,且句子级别的信息能较好保留
语义捕捉能力仅通过词频和文档频率来表示词语重要性,语义能力较弱捕捉到词与词之间的语义相似性在更深层次上理解词汇之间的关系,能捕捉多层次的语义信息
训练与应用难度较低,依赖统计方法,易于理解与实现需要预训练的词向量模型,训练和调优过程较复杂需要大量计算资源和预训练的BERT模型,应用较复杂
适用场景适用于短文本、关键词提取、文档检索等适用于文本分类、情感分析等语义相关任务适用于需要强语义理解的复杂任务,如问答系统、对话生成等
计算复杂度低,训练和推理速度快中等,需要训练词向量,计算稍慢高,需要大规模的预训练模型,计算开销大

集成算法

我们应该都听过关于合作的谚语,比如“三个臭皮匠,顶个诸葛亮”、“众人拾柴火焰高”、“兄弟齐心,其利断金”等,这其实就是集成算法(Ensemble Learning)的核心思想——通过组合多个弱学习器,提升整体模型的性能

集成算法

如图片所示,为了获得准确的预测结果,我们会把多个弱学习器(弱学习器是指,在某些情况下表现不佳,准确率较低的单个模型。比如,单棵决策树)集成一个具有更高准确度的强学习器。对于分类问题,一般使用投票机制,即每个模型预测一个类别,最终结果是各个模型预测类别中票数最多的那个类别(众数);对于回归问题,一般使用加权平均,将每个模型的预测值按某种方式加权平均,得到最终的预测值(均值)。

一般来说,集成算法有两种策略:

袋装法(Bagging:通过对训练集进行多次随机抽样(有放回的抽样),生成多个不同的子数据集。然后,分别在这些子数据集上训练多个模型(例如,多棵决策树)。最终,通过将这些模型的预测结果进行投票或平均,得到最终的预测结果。其主要的应用是随机森林,通过在多个子数据集上训练决策树并且随机选择特征进行节点划分,从而增加模型的多样性。

提升法(Boosting:提升法通过逐步训练多个模型,每个模型都在前一个模型的基础上进行改进。每次训练时,会根据之前模型的错误来调整样本的权重,让后续模型更多地关注之前模型错误的样本。最终,通过将所有模型的预测结果加权平均或投票得到最终预测结果。主要包括梯度提升决策树和XGBoost。

随机森林

随机森林的基本原理

在决策树部分我们提到,传统决策树通常考虑所有的特征来寻找最佳分裂点,也就是在每个节点选择使信息增益或基尼指数最大化的特征,其隐藏的问题是模型过拟合(对未知的测试数据泛化能力弱)。为了防止过拟合,我们会使用随机森林(Random Forest),即在每个节点分裂时,不使用所有特征,而是随机选择一小部分特征来进行分裂从而生成多棵相互独立的决策树。这样可以增强树之间的多样性,减少过拟合风险。

举个生活中的例子。

我们需要根据学生的学习情况预测他们能否通过考试。我们知道学生的一些学习特征:学习时间、上课出勤率、作业完成情况、模考成绩。 基于随机森林的集成算法,我们根据这四个特征创建多棵决策树:

树1:根据学习时间和模拟考试成绩来判断一个学生能否通过考试。 树2:根据上课出勤率和作业完成情况进行判断。 树3:考虑学习时间和作业完成情况。

之后我们让每棵决策树基于所选特征和数据来判断一个学生能否通过考试:

树1:预测某个学生不能通过考试。 树2:预测该学生能通过考试。 树3:预测该学生不能通过考试。

最后,通过“投票”来预测最终结果。在3棵决策树中,2棵认为不能通过1棵能通过,因此随机森林最终预测该学生不能通过考试。

随机森林的基本逻辑和步骤如下:

第一步,从样本集中以有放回抽样的方式随机选出训练样本(Bootstrap Sampling。从原始训练集(假设有N个样本)中随机抽取n个子样本,用有放回的抽样方式意味着一个样本可能在多个树中出现,也可能在任何一棵树中没有出现。因此,每棵树的训练数据集是不同的。

第二步,从所有属性中随机选择k个属性(假设共有P个属性),并选择最佳属性进行分割。在每个节点上,随机选择k个特征(通常k<P),而不是考虑所有P个特征。然后,基于这k个随机选出的特征,选择最佳的特征进行节点分裂。这样增加了树之间的多样性,有助于减少过拟合。(让树完全生长,不进行剪枝)。

第三步,重复上述两个步骤m次,创建m棵决策树。重复步骤1和2m次,创建m棵独立的决策树。每棵树都在不同的训练数据子集和特征子集上训练,保证它们之间有较大的差异性。

第四步,m棵树形成随机森林,通过投票/平均决定数据的预测结果。对于分类问题通过m棵树的“投票”来决定最终的分类结果;对于回归问题通过m棵树的平均预测值来得到最终结果。

随机森林的操作代码

随机森林适合处理高维特征的输入样本,因而我们使用sklearn模块自带的乳腺癌数据集作为示例。该数据集包含了乳腺癌的相关数据,共有569个样本,每个样本有30个特征,目标变量是一个二分类标签(良性或恶性)。

为了提高预测准确性,我们需要调参。在随机森林中,可以调整的超参包括:

n_estimators,决策树的数量,用于控制随机森林中树的数量。可以通过交叉验证来选择最佳的树数量。

max_depth,每棵决策树的最大深度,可以设置适当的深度来控制树的复杂度。较小的深度有助于减少过拟合,但如果过小可能会欠拟合。

min_samples_split,分裂一个节点所需的最小样本数,用于控制每个内部节点的最小样本数,防止模型在训练时过于细化,导致过拟合。

max_features,每棵树分裂时考虑的特征数,用于控制每棵树在分裂时可以考虑的特征数量。可以是整数、浮动值或auto使用所有特征)。

bootstrap,是否采用自助采样。用来控制是否对数据进行自助采样。通常设为True,表示随机森林中的每棵树都会使用自助采样。

criterion,分裂的标准。gini是默认值(基尼不纯度),entropy则是信息增益。

我们分别使用网格搜索与随机搜索演示调参过程。

(1)网格搜索

(2)随机搜索

梯度提升树算法

梯度提升树算法的基本原理

(1)梯度提升树算法的原理

从字面意思理解,梯度提升树(GBDT)由两部分组成“梯度提升(Gradient Boosting,GB)”+“决策树(DT)”。决策树的原理我们在传统分类算法的决策树部分就提到过了,而梯度提升则又可以分成梯度(Gradient)和提升法(Boosting)。

梯度是一个向量,表示某个函数在某个点的变化最快的方向,简单来说,它告诉我们如何调整输入变量,使函数值变化最快。在一元函数中,梯度就是切线的斜率。

梯度

如图所示,一元函数的梯度就是导数f(x)=ΔyΔx。对于多元函数f(x1,x2,...,xn),梯度是由偏导数组成的向量f=(fx1,fx2,...,fxn)。这个向量的方向,表示函数值增长最快的方向,向量的大小(模长)表示增长的速率。类比爬山,梯度就是最陡的上坡方向(最快爬到山顶的方向)。

提升法是一种集成学习的方法,核心思想是迭代地训练一系列弱学习器,每个学习器都试图修正前一个学习器的错误。随机森林中的每个弱模型要求模型之间相互独立,但在提升法中每个弱模型是一种嵌套关系。每个新模型专门学习前面模型的错误,不断优化模型性能,最终将多个弱模型组合成一个强模型。

梯度提升结合了梯度下降和提升法。简单来说,提升法是通过不停迭代从而改进模型,梯度是找到减少误差最快的方向,梯度提升就是让新的模型沿着损失函数的梯度方向进行调整,以提高整体模型的准确性。

因此,简单而言GBDT(Gradient Boosting Decision Tree,梯度提升决策树)是一种集成学习方法,它通过梯度提升结合多个决策树模型来进行预测。其基本原理如下:

第一步,初始化模型。GBDT会先用一个简单的模型(通常是一个常数)进行初始化预测。这个模型可能是所有目标值的均值或中位数。

第二步,计算残差。接下来GBDT会计算当前模型预测值与真实值之间的差异(残差),残差表示当前模型未能拟合的数据部分。

第三步,拟合残差。在每一轮迭代中,GBDT会训练一个新的决策树来拟合当前的残差(模型根据残差来进行优化,而非真实值)。

第四步,更新模型。在每轮迭代结束后,将当前模型与新训练的树进行加权累加,更新当前的预测模型。

第五步,重复训练。重复第二步至第四步,直到达到预设的最大树数或者模型性能收敛。

举个生活中的例子。

假设我们要预测房价,现实中的房价是80万,而初始模型给出的预测是70万,此时的差距(残差)为10万。接下来,我们训练一棵新的决策树用以拟合残差。假设第二棵树的给出的预测值是6万,那么模型的预测值变成了70+6=76万,而模型的残差也变成了80-76=4万。接下来我们训练第三棵树,拟合新的残差(此时残差为4万)。假设第三课树的拟合结果是3万,则预测值变成了76+3=79万,预测值与真实值的残差也缩小至80-79=1万。循环反复,直到预测值完全等同于真实值。

(2)梯度提升树算法的数学推导

从数学的角度来说,提升树算法的核心思路其实就是加法模型与残差拟合。GBDT采用加法模型逐步逼近残差,在每一次迭代中通过训练一棵新的决策树来拟合上轮模型的残差,实现对预测结果的逐步优化,以最小化整体损失函数。我们以回归问题举例。

提升法采用加法模型,因而提升树模型的数学表达式可以写为:

(92)F(x)=Ft1(x)+ht(x)

其中,F(x)是当前模型的预测值;Ft1(x)是前一轮(t1)的模型预测值;ht(x)是第t轮模型的预测值,用于拟合当前轮的残差(负梯度)。

我们的目标是让损失函数最小,即真实值与预测值的差最小:

(93)argmini=1nL(yi,Ft1(xi)+ht(xi))

其中,yi表示第i个样本的真实值,L(yi,Ft1(xi)+ht(xi))是损失函数。在回归问题中,我们一般使用MSE作损失函数,因而GBDT拟合的残差为:

(94)L(yi,Ft1(xi)+ht(xi))=(yiFt1(xi)ht(xi))2(95)=(yiF(x))2

我们对损失函数求偏导:

(96)(yi,F(x))F(x)=2(yiF(x))

由于2(yiF(x))和梯度方向完全相反,我们将其称作负梯度。而在回归问题中,因为残差是yiy^i。因此,我们将负梯度近似为残差。第t轮的残差为:

(97)rit=(yiFt1(xi))

用以表示上一轮模型Ft1的预测值和真实值之间的差距。我们训练决策树来拟合这些残差,使得拟合效果最好:

(98)ht(x)=argminhi=1n(rith(xi))2

换言之,这相当于在第t轮通过训练一棵决策树来预测t1轮的残差。经过T轮迭代后,最终的模型是所有决策树的加总:

(99)FT(x)=F0(x)+i=1Tht(x)

梯度提升树算法的操作代码

我们用sklearn模块中糖尿病数据集进行演示。这是一个回归问题集,包含了来自442名患者的10个特征,目标是预测患者一年的疾病进展,即目标变量是一个连续的数值,代表糖尿病的进展程度。

GBDT的超参数包括几类:

第一类:模型结构相关的参数

n_estimators是决策树的数量,通常决策树的数量越多模型的准确性也越多,但这容易导致过拟合问题。

learning_rate学习率,用来控制每棵树对最终模型的贡献。较低的学习率(如0.01或0.1)通常能够提高模型的泛化能力,但需要增加n_estimators的数量来补偿低学习率的影响。

max_depth是每个树的最大深度。

min_sample_split是一个内部节点再划分所需的最小样本数。

min_samples_leaf是一个叶子节点的最小样本数。

subsample是训练每棵树时使用的数据比例(类似于随机森林中的Bagging)。

第二类:树的参数

max_features是每棵树分裂时使用的最大特征数量。可以设置成max_features='auto',所有特征;max_features='sqrt',特征的平方根;max_features='log2',特征的对数。

第三类:损失函数

loss用于优化损失函数。对于回归问题,默认使用loss='ls',即最小二乘法;对于分类问题,默认使用loss=deviance,即对数似然损失。

在调参上,常用网格搜索与随机搜索寻找最佳参数。

(1)网格搜索

(2)随机搜索

XGBoost

XGBoost算法的基本原理

(1)XGBoost算法的原理

简单而言,XGBoost(Extreme Gradient Boosting)是GBDT的全面升级,核心思想是在每轮迭代中拟合残差。不同的是,XGBoost不仅在原始的损失函数上做梯度下降,还加上了正则化项以避免过拟合。此外,在GBDT中,每一轮的树构建是通过梯度下降的方法来拟合残差,也就是用当前模型的预测值与实际值之间的差异来构建新的树。而XGBoost在此基础上引入了二阶泰勒展开,以更精确的方式来近似损失函数,并加速训练过程。

因此,相较于GBDT,XGBoost具有精准度更高通过引入二阶导数信息来优化模型更新,XGBoost能够更精准地调整每轮迭代的预测)、灵活性更强XGBoost支持多种自定义损失函数和优化目标,适用于更广泛的问题场景)、防止过拟合通过正则化项控制模型复杂度,减少过拟合的风险)、学习速率更快采用分步优化和高效的计算机制,使得每轮迭代能够更快速地收敛)、支持特征抽样XGBoost允许在训练过程中对特征进行随机抽样,从而降低模型的方差和提高泛化能力)等优点。

(2)XGBoost算法的数学推导

XGBoost也是一个加法模型:

(100)F(x)=i=1Tht(x)

其中,ht(x)表示第t棵树,T是树的总数。

为了防止过拟合,我们在模型中加入正则化项,从而目标函数为:

(101)i=1nL(yi,F(xi))+i=1TΩ(ht)

其中,L(yi,F(xi))是损失函数;Ω(ht)是正则化项,通常为树的复杂度,也可写作:

(102)Ω(ht)=γT+12λi=1Twj2

T是树的总数,γλ是控制树的复杂度的正则化参数,wj是树中每个叶子的权重。

由于XGBoost算法使用损失函数的二阶泰勒展开作为代替函数,因此可以写作:

(103)gi=yi,F(xi)F(xi)(104)hi=2(yi,F(xi)F(xi)2(105)L(yi,F(xi))(yi,Ft1(xi))+gi(F(xi)Ft1(xi))+12hi(F(xi)Ft1(xi))2

gihi分别是损失函数的一阶导数和二阶导数,Ft1(xi)是上一次迭代的预测值。因为是嵌套关系,每棵树可以被看作是若干个叶子结点wj,即每个样本xi被划分到每个叶子结点j时,该预测值就是该叶子的权重wj。现如今我们需要找到一棵新树wj使得损失函损最小,将其带入损失函数后:

(106)L(yi,F(x)+wj)L(yi,F(x))+giwj+12hiwj2

由于L(yi,F(x))是上一轮的损失值,是固定常数,与新树无关。同样的,因为γT是个固定值,目标函数可写作:

(107)j=1TiIj(giwj+12hiwj2)+12λj=1Twj2)=j=1T[iIjgiwj+12(iIjhi+λ)wj2]

即,目标函数变成了一个关于叶子结点wj的二次函数,对其求导后令其为0:

(108)iIjgi+(iIjhi+λ)wj=0(109)iIjgiiIjhi+λ=wj

将其重新带入目标函数后,得到每棵树的得分:

(110)j=1T[iIjgiiIjgiiIjhi+λ+12(iIjhi+λ)(iIjgi)2(iIjhi+λ)2]+γT=12j=1T(iIjgi)2iIjhi+λ+γT

其中,第一项衡量树的拟合效果,即叶子节点的梯度之和越大,分母越小(说明梯度变化小),这一项越负,模型的损失就越低,模型越好。换言之,我们的目标就是选择最优的树结构,使得损失下降最多。

XGBoost算法的操作代码

我们同样使用sklearn模块中的糖尿病数据集进行演示。

为了提高模型性能,我们调整以下超参。

n_estimators,树的数量。

learn_rate,学习率,控制每棵树对最终预测的影响。

max_depth,树的最大深度。

min_child_weight,每个叶子结点最小样本权重和。

subsample,每棵树训练时随机选取的样本比例。

colsample_bytree,每棵树随机选择特征的比例;colsample_bylevel,每层随机选择特征的比例;colsample_bynode每个节点随机选择特征的比例。

reg_lambda,L2正则化,通过惩罚权重的平方控制模型的复杂度。

alpha,L1正则化,通过惩罚权重的绝对值控制模型的复杂度。

gamma,最小分裂增益,控制树的分裂。

max_delta_step,最大特征数。控制每棵树的最大步长,帮助收敛并防止不稳定性。

由于演示的例子是个回归问题,因此设置的模拟器是xgb_model = XGBRegressor(),如果是分类问题是需要改成xgb_model = XGBClassifier()

参数objective是用来判断不同任务的。如果是回归任务,objective可以选择reg:squarederror:用于最小化均方误差(MSE);reg:logistic:用于逻辑回归;reg:gamma:用于解决具有偏态分布的数据,适合用于Poisson回归。如果是分类任务,则可以选择binary:logistic:用于二分类问题,输出的是一个概率值(在[0, 1]之间);binary:logitraw:用于二分类问题,输出的是对数几率(log-odds);multi:softmax:用于多分类问题,输出为类别的概率分布(选择最大概率对应的类别);multi:softprob:用于多分类问题,输出为每个类别的概率。如果是排名任务,可使用rank:pairwise:用于排序问题,基于成对比较来优化模型;rank:ndcg:使用NDCG(Normalized Discounted Cumulative Gain)作为优化目标,常用于信息检索任务。

我们分别使用网格搜索和随机搜索演示调参过程。

(1)网格搜索

(2)随机搜索

总的来说,随机森林、GBDT和XGBoost的区别如下。

特性随机森林GBDTXGBoost
学习类型装袋法提升法提升法
训练方式并行训练各树顺序训练,每棵树纠正前一棵树的错误顺序训练,但支持并行计算
模型复杂度模型简单,易于实现模型较为复杂,调参较难相比GBDT更为复杂,增加了正则化和优化技巧
对过拟合的防范通过构建多个树来减少过拟合通过优化残差,但容易过拟合引入正则化(L1、L2)有效防止过拟合
训练速度训练速度较慢,但可以并行处理多个树训练速度较慢,尤其是深度大的树相比GBDT更快,使用并行计算提高了效率
预测精度较高,适合多种任务精度高,尤其在处理非线性问题时表现更佳精度最优,特别是在大规模数据和复杂任务中
超参数调节需要调节树的数量、深度等调参较复杂,需要调节多个超参数(学习率、树深等超参数更多(正则化、列抽样等),调节更复杂
内存和计算资源占用内存较大,尤其在数据量较大时占用内存适中,但依然较为消耗资源内存占用较大,尤其是在大数据集上
适用场景分类、回归问题,适合特征较多的数据集非常适合分类、回归任务,特别是数据非线性的场景分类、回归、排序任务,适合大规模数据处理任务

随机森林适用于快速开发和不需要过多调参的任务,尤其在数据量较大、特征丰富的情况下表现好;GBDT适用于对精度要求较高的任务,但需要较长时间的训练和参数调节;XGBoost是GBDT的优化版本,速度更快、精度更高,并且能够防止过拟合。对于复杂和大规模的数据集,它通常是最好的选择。我们最好能根据需要和数据集的特点,选择合适的集成算法。


无监督学习算法

在总论部分我们提到,有监督学习和无监督学习的区别在于是否存在已知标签(响应变量),因此无监督学习是让计算机从数据中帮助我们发现模式、结构和关系,从而对数据进行聚类、降维等后续操作。

举个例子。

我们去打猎。有监督学习就像是我们已经知道目标是什么(如捕捉鹿),然后训练模型去捕捉鹿;无监督学习就像我们在森林中漫无目的地探索,最终根据我们观察到的特征和规律去发现有可能是鹿、兔子或老虎的区域。

因此,无监督学习又常常会被当作有监督学习的基础。一般来说,无监督学习的主要任务包括:聚类将数据集中的样本按照相似性分成多个组或簇。每个簇中的样本尽可能相似,而不同簇的样本则尽量不同)、降维通过将高维数据映射到低维空间来减少数据的维度,同时尽可能保留数据中的关键信息。降维可以帮助减少计算负担、避免过拟合以及使数据更容易可视化)、密度估计估计数据分布的概率密度函数,从而了解数据的分布特性)、关联规则学习发现数据中项与项之间的关联关系,常用于市场篮子分析,挖掘哪些商品经常一起购买)、主题建模从大量文本数据中自动识别潜在的主题或话题)。

实际上,无监督学习的应用类型很多,在本章中我们将介绍适用于社会科学中的主流无监督学习算法。

聚类算法

作为无监督学习算法之一,聚类(clustering)没有绝对的“正确答案”,其输出结果有赖于分析者的自我判断。尽管我们有多种评估聚类结果的方法,但聚类仍然无法解决主观性问题。我们只能根据应用场景选择最合适的算法,从而赋予聚类结果意义与价值。

簇(cluster)是聚类最核心的概念。簇是聚类算法的输出,表示在数据集中,彼此之间相似的数据点被归为一类。簇的定义可以根据不同的聚类算法而有所不同,但通常簇的内部数据点相似度较高,而簇之间的相似度较低。聚类的核心目标就是通过算法将数据点分配到不同的簇中,使得同一簇内的点尽可能相似,而不同簇之间的点尽可能不同

对于相似度的度量,我们在KNN部分就已经提及了,主要包括:距离度量(欧氏距离、曼哈顿距离)、相似性(余弦相似度、皮尔逊相关系数)、匹配(杰卡德相似度)。我们接下来会介绍三种使用欧氏距离的算法:K-means算法、层次算法和DBSCAN算法。

K-means聚类算法

K-means聚类是常见的无监督学习算法,用于将数据集划分成K簇(群集)。通过反复迭代来优化簇的划分,使得个簇内的数据点尽量相似,不同簇的数据点尽量不同(比如说,告诉机器森林中可能有三种动物,然后机器通过K-means算法找出鹿、兔子和老虎)。

(1)K-means聚类算法的原理

k-means算法非常直观,基本步骤如下:

第一步,随机选择K个数据点作为初始的聚类中心

第二步,对每个数据点,计算它与K个聚类中心的距离,并将每个数据点分配到距离它最近的聚类中心

第三步,对于每个簇,计算该簇内所有点的均值,并将聚类中心更新为新的均值

第四步,重复第二步和第三步,直至聚类中心收敛(不再发生变化或变化非常小

K-means聚类过程

正如图片中展示的。假设我们需要将数据分成两簇(K=2),机器会帮我挑选2个初始聚类中心(质心),并计算每一个样本点到这个两个初始中心的距离,从而进行初步聚类(图b到图c)。接着,针对初步聚类所形成的簇,计算这个簇中所有的点的均值,从而找到新的聚类中心(图c到图d)。之后,以新的聚类中心出发,重新计算每一个样本点到这个新的质心的距离,从而进行二次聚类(图d到图e)。最终,经过多次反复,直到两个质心不再发生变化或变化非常小,获得最终聚类结果(图e到图f)。因此,K-means的目标是最小化每个簇内的平方误差(SSE),即每个数据点到其所属簇中心的距离平方和最小:

(111)argminj=1KxiCj||xicj||2

其中,K是指定的簇的个数;Cj代表第几个簇;xi表示属于簇Cj的数据点;cj表示簇Cj的质心(中心点);||xicj||2是数据点xi到质心cj的距离平方。

K-means的优点很直观,简单高效、收敛性快、可拓展性强。但同时,其缺点也很突出,需要预设簇数K(用户事先设定簇的个数)、对初始聚类中心敏感(不同的中心选择可能导致不同的聚类结果)、对噪声和离群值敏感、对簇的形状要求较高(K-means假设簇的形状是球形的,因而对于一些不太规则的簇而言,该算法可能不太适用)。

因此,和KNN算法类似,K值的选择对算法结果至关重要。选择K值的常用方法包括:

肘部法则(Elbow Method,其原理是通过计算不同K值下聚类结果的SSE来寻找最合适的“肘部”位置,即最佳的簇数。步骤大致包括:

第一步,对不同的K值进行K-means聚类(比如,1到10)。

第二步,计算每个K值下的SSE(每个点到其簇中心的距离平方和)。

第三步,绘制K与SSE的关系图,并选择SSE开始“拐弯”(肘部)的那个K值。

轮廓系数(Silhouette Score,用于衡量样本的紧密性和与其他簇的分离程度。其取值范围为[-1, 1],值越接近于1表示聚类效果越好,越接近于-1表示效果较差。其公式如下:

(112)s(i)=b(i)a(i)maxa(i)b(i)(113)={1a(i)b(i)a(i)<b(i)0a(i)=b(i)b(i)a(i)1a(i)>b(i)

a(i)表示数据点i到同簇其他点的平均距离(簇内距离),b(i)表示数据点i到最近簇的平均距离(簇间距离)。因此,轮廓系数的目标就是使所分的簇内距离最小而簇间距离最大。其步骤如下:

第一步,对不同的K值进行K-means聚类。

第二步,计算每一个点的轮廓系数,并取平均值。

第三步,选择平均轮廓系数最大值的K值。

除此之外,为了避免K-means对初始值过于敏感的问题,我们使用K-means++代替K-means。它是通过增大初始簇中心之间的距离,减少局部最优的可能性,加快收敛速度。具体来说,我们在给定K值后,K-means++会随机选择第一个簇的质心,计算每一个数据点到已选簇的质心的距离。之后构造一个概率分布P(xi)=D(xi)jD(xj),分子D(xi)表示数据点xi到已有簇质点的最小距离的平方,是所有点的最小距离平方和。换句话说,距离已选簇中心的数据点越远,被选为新中心的概率就越大。之后反复上述步骤,直到选出K个簇质心。最后,用K-means算法进行质心的迭代。简言之,不同于K-means随机选取K个点,K-means++根据概率选择初始点,避免了随机点之间过于接近的问题。

(2)K-means算法的操作代码

在示例部分,我们选择鸢尾花数据集。该数据集有150条数据,4个特征。其中,真实的类别为3种鸢尾花(Setosa、Versicolor、Virginica),但无监督学习是不知道具体标签的,因此我们只用特征进行聚类。

上一部分我们提到,K值的选择对聚类结果非常重要。所以,我们接下来会演示在不知道鸢尾花类别的情况下如何通过肘部法则和轮廓系数来选择合适的K值。我们假定,K值的选取范围在2到10。

一般来说,在K-means聚类算法中常用的参数有:

k_clusters,指定聚类的簇数K。

init,初始质心的方式,有k-means++random随机选择)。

n_inti,运行K-means算法的次数。用于避免因随机初始化质心而导致的局部最优解。默认值是10,表示会运行10次K-means,并选择最好的结果。

max_iter,每次运行时的最大迭代次数。如果聚类没有在max_iter次迭代内收敛(即质心不再发生变化),则停止。默认值300。

tol,收敛容忍度。用于判断算法是否已经收敛。当质心变化的幅度小于tol时,算法会停止迭代。默认是1e-4。

precompute_distances,是否预先计算距离,默认为'auto'

algorithm,使用的K-means算法。包括auto:自动选择最适合当前数据集的算法(默认值);full:标准的K-means算法(即,Lloyd算法);elkan:Elkan K-means算法,优化了欧氏距离的计算,适用于高维数据。

层次聚类算法

(1)层次聚类算法的基本原理

层次聚类(Hierarchical Clustering)是一种常见的无监督学习方法,用于将数据集中的样本点按层次结构进行聚类。与K-means聚类不同,层次聚类不需要预设簇的个数,而是通过自底向上或者自顶向下的方式,将数据逐步合并或拆分为不同的簇,形成一个树状结构,也叫树形图(dendrogram)。

层次聚类的基本原理,是通过计算数据点之间的相似度(或距离),然后根据相似度将数据点逐步聚合或拆分成簇

一般来说,层次聚类的方法包括:自上而下(Divisive Clustering)和自下而上(Agglomerative Clustering)两种。自上而下的层次聚类是在初始时将所有样本点都归属为一个簇,之后在每次迭代中选择最不相似的簇进行拆分,直至满足停止条件(如指定簇数K或者簇的大小达到预设的阈值);自下而上的层次聚类则是在初始时将每一个样本点都看成一个独立的簇,在每次迭代中选择两个最相似的簇进行合并,直到所有的数据点都合并成一个簇,或者达到某个停止条件(如指定簇数K或者合并的距离过大)。

层次聚类的步骤很简单,其核心就是根据计算出的距离来逐步合并或分裂簇:

第一步,计算相似度(距离)矩阵。对于每一对数据点,计算它们之间的距离(例如欧式距离、曼哈顿距离等),得到一个相似度矩阵。

第二步,选择两个最相似的簇。在所有的簇中,选择距离最小(或相似度最大)的两个簇进行合并,或者选择拆分的簇(对于自顶向下的层次聚类)。合并的方法根据所选的聚类策略而不同:单链接,将两个簇之间的距离定义为簇中最接近的两个点之间的距离;完全链接,将两个簇之间的距离定义为簇中最远的两个点之间的距离;平均链接,将两个簇之间的距离定义为簇中所有点对之间的平均距离;Ward方法,选择两个簇合并,使得合并后的簇内部的平方误差和最小化。通过最小化簇内的方差来确定哪些簇需要合并。

第三步,更新距离矩阵。在合并两个簇之后,更新簇之间的距离矩阵。新的距离矩阵需要重新计算,以反映新簇的存在。对于自底向上的聚类方法,合并后的新簇的距离需要计算它与其他簇之间的距离。

第四步,重复第二步和第三步。重复选择最相似的两个簇合并,直到满足达到预定的簇数或所有数据点最终合并为一个大簇。

第五步,生成树形图。聚类过程生成一个树形结构,表示各个簇如何合并。树形图可以帮助我们根据不同的层次选择合适的簇数(在树形图中,水平距离表示样本间的相似度,树的高度表示合并的距离)。

总的来说,层次聚类的优点在于不需要预设簇数,且能够处理任意形状的簇。但在缺点上,层次聚类会考虑每一个数据点,因此对噪声和异常值非常敏感。此外,随着数据维度的增加,距离将不再能有效区分簇之间的相似度,因此层次聚类面对高维数据可能会遇到维度灾难(需要考虑降维处理)。

(2)层次聚类算法的操作代码

我们同样以鸢尾花数据集作为示例。

总的来说,层次聚类的参数调整通常围绕合并策略(method)、距离度量(metric)、截断树状图(truncate_mode)、距离阈值(distance_threshold)等展开。

method合并策略,可选ward,最小化方差的合并方法(最常用,适合球状簇);single,最近邻方法,合并簇间距离最小的两个簇(适用于链状簇);complete,最远邻方法,合并簇间距离最大的两个簇(适用于分布较分散的簇);average,均值连接方法,合并簇间距离为两个簇中所有点之间的平均距离;centroid,以簇的质心来计算距离。

metric距离度量,可选euclidean,欧氏距离(默认);cityblock,曼哈顿距离;cosine,余弦相似度;hamming,哈明距离;mahalanobis,马氏距离。

optimal_ordering,是否按顺序排列。默认情况下,linkage函数的树状图没有对簇进行优化排序。在某些情况下,启用optimal_ordering=True可以帮助更清晰地展示树状图结构。

truncate_modep,截断树状图。当数据量很大时,可以选择截断树状图,只显示前p个聚类,避免树状图过于冗长。truncate_mode,控制截断方式,可选levelmlablevel表示根据层次深度截断,mlab表示根据簇数截断。p,控制要保留的层次深度或聚类数。例如dendrogram(Z, truncate_mode='level', p=5)

distance_threshold,指定距离阈值。如果想手动指定一个距离阈值来决定合并簇的条件,可以使用distance_threshold参数。如果设置该参数,则Z变量会返回一个距离矩阵而非树状图,这时可以直接使用fcluster来获取最终簇数。例如,clusters = fcluster(Z, t=5, criterion='distance')

fcluster,通过距离或簇数得到最终簇。使用fcluster函数可以根据距离阈值或者簇数来获取最终的簇划分。fcluster可以基于距离或者最大簇数来选择。t是阈值(距离或簇数);criterion可选择'distance''maxclust'根据最大簇数来确定)。例如,clusters = fcluster(Z, t=3, criterion='maxclust')

DBSCAN聚类算法

(1)DBSCAN聚类算法的基本原理

DBSCAN(Density-Based Spatial Clustering of Applications with Noise)是一种基于密度的聚类算法,适用于发现形状不规则的簇,并且能够自动识别噪声点。它的原理主要基于数据点之间的密度,利用密度相连的思想来形成簇。简单来讲,DBSCAN聚类算法是通过一些列的条件判断来确定数据点的归属。其主要围绕密度可达和密度相连两个概念展开。

概念一:邻域(Neighborhood。在DBSCAN中,数据点p的邻域定义为距离点p小于或等于某个阈值ϵ的所有点集合。在数学的形式上为:

(114)Nϵ(p)={q|D(p,q)ϵ}

其中,Nϵ(p)是点p的邻域,D(p,q)是点pq之间的距离。

概念二:核心点(Core Point。核心点是指其邻域内包含至少minPts个点的点(Minimum Points,最少样本点,是确定核心点的重要参数)。换言之,如果点p的邻域内有最少样本点或更多点(包括点p),则点p是一个核心点,即|Nϵ(p)|minPts

概念三:边界点(Border Point。如果点p不是核心点,但它的邻域内至少包含一个核心点,则p是一个边界点。边界点属于某个簇,但它不是核心点。

概念四:噪声点(Noise Point。如果一个点既不是核心点也不是边界点,那么它就是噪声点。

概念五:密度可达(Density Reachability。密度可达是DBSCAN的核心概念之一,简单来说,如果点p和点q都能通过某个核心点链接起来,那么我们就说它们是密度可达的。点p和点q密度可达意味着通过一个核心点可以将二者链接起来,这个链接基于密度,即它们之间的距离小于阈值ϵ,且中间可以通过其他核心点链接。

概念六:密度相连(Density Connectivity。如果点p和点q可以通过一个或多个核心点相连,则称它们密度相连。

基于上述概念,DBSCAN算法的聚类过程如下:

第一步,从未访问的点中选择一个点,检查该点是否是核心点

第二步,如果是核心点,将该点标记为簇的一部分,并从该点的邻域中扩展簇。将邻域内的其他点进行同样的处理,直到扩展完成。如果不是核心点,但它在某个核心点的邻域内,那么它会被分配到该核心点所属的簇中,并将其标记为边界点;如果一个点既不是核心点,也不是边界点,那么它被标记为噪声点,不属于任何簇

第三步,继续对未访问的点重复第一步,直到所有点都被访问

第四步,返回形成的簇和噪声点

举个直观的例子。

如果我们有一个数据集想用DBSCAN进行聚类,首先,我们设置ϵ=0.5 和 minPts=4。然后,算法会按如下步骤进行: 1、选择一个未访问的点,计算其邻域; 2、如果邻域内点数大于等于4,标记该点为核心点,并扩展簇;否则标记为边界点或噪声点; 3、对扩展出来的点继续执行上述步骤,直到所有点都被访问过; 4、输出最终的簇。

通过这样的方式,DBSCAN能够将数据分成多个簇,并自动标记离群点。因此,DBCSCAN的优点在于不需要指定簇的数量、能够发现任意形状的簇且可以识别噪声点。但同时,BDSCAN对参数要求很高,即聚类效果高度依赖于定义邻域的半径ϵ和簇中必须包含的最少点数minPts

(2)DBSCAN聚类算法的操作代码

在DBSCAN聚类算法的操作代码中,我们使用sklearn模块中的make_moon函数,随机生成一个月牙形的数据集作为示例。

如前面提到的,DBSCAN聚类算法最核心参数为邻域半径eps和最小样本数min_samples

过大的邻域半径会被看作一个簇导致过拟合,而过小又会将许多点标记成噪声点。因此,对于邻域半径的选择,可以使用KNN算法衡量每个点与其邻居之间的距离,从而了解数据点的局部密度。

拐点位置对应的y值即为邻域半径的合理值。

最少样本数的选择依赖于经验,一般会选择min_samples=2*数据维度例如,2D数据用4个最少样本数),以及可通过网格搜索进行交叉测试进行选择。在示例部分,我们通过网格搜索调整epsmin_sample,并根据轮廓系数silhouette_score来确定最佳的聚类参数。

总的来说,K-means聚类算法适合大规模、结构化数据,但对噪声敏感,适用于球形簇;层次聚类算法适用于小规模数据,无需预设簇数,但计算量大;DBSCAN聚类虽然适用于任意形状的簇,能够识别噪声,但对密度参数敏感。

特性K-means层次聚类DBSCAN
基本思想基于质心的划分递归合并/拆分数据点基于密度的聚类
需要指定簇数是(必须指定K否(可通过树状图选择否(但需调整epsminPts
对噪声的处理容易受异常值影响受距离度量影响可识别噪声点
簇的形状适用于球形簇适用于不同尺度的簇适用于任意形状的簇
计算复杂度低(O(nkT)高(O(n²)中等(O(nlogn)
适用于大数据是(可扩展否(计算量大是(适用于大规模数据
可解释性低(依赖初始中心点高(树状图可视化中等(密度参数影响较大
适用场景结构化数据,数据量大需要层次关系的场景空间数据、噪声多的场景

降维算法

降维是种给数据“瘦身”的方式,其核心在于保留数据关键信息的同时减少数据维度特征数量)。举个直观的例子:

假设我们有一组民调数据,其中包括五个变量:政府信任度、民主满意度、社会公平感、政治参与度、媒体使用情况。这五个变量都可以用来衡量选民的政治态度,但每个变量之间可能存在高度相似。因此直接使用这些数据可能存在数据维度过高或共线性问题。 对此,我们可以先计算每个变量的相关性,形成一个相关性矩阵,之后采取一些手段减少维度(例如,将政府信任度和政治参与度合成一个新变量;民主满意度、社会公平感、媒体使用情况合成另一个新变量),继而由原来的五个变量压缩至两个。最后,我们对新生成的两个变量进行解释。

大致来说,降维的方式分线性降维和非线形降维两种。其中,线性降维主要包括主成分分析和线性判别分析,非线形降维主要包括t-SNE和UMAP。尽管非线形降维同样能够提取变量特征,但这些特征通常难以直接解释,只适用于数据可视化而非明确的特征分析。因此,在降维算法中我们主要介绍主成分分析。

主成分分析算法的基本原理

正如其名,主成分分析(Principal Component Analysis,PCA)的核心思想很简单,通过特征值分析协方差矩阵,从而在多维数据中找到最能表示这些特征的主成分。之后将原始数据投影到这些主成分中,达到降维的目的。我们刚刚提到的民调数据例子,就是用的主成分分析。

主成分分析

如图所示。现在有个多维特征的数据集,我们将其投射到二维空间中。可以发现,数据点几乎沿着F1方向上的直线分布,而在垂直于这条直线的方向上几乎没有任何变化,即F2方向上的数据点方差很小。换言之,F1方向的特征方差最大(特征之间的离散性高)。所以,将原始数据投射到该方向上能最大限度的保留信息的同时,减少特征维度。这个F1通常被称作主成分,PCA的目标就是找到这个方向。

因此,PCA的基本原理就是,通过找到方差最大的方向(数据变化最大的方向),将数据投影到这个方向上实现降维,同时保留数据中的最大变异性(信息量

假设我们有一个数据集X,包含n个样本,每个样本有d个特征。即数据矩阵为:

(115)X=[x11x12x1dx21x22x2dxn1xn2xnd]

其中,X是一个n×d的矩阵,xnd表示第n个样本在第d维的数值。

由于d个特征之间可能具相关性(降维的前提是,特征之间存在一定的相关性或信息冗余),我们将数据进行标准化处理X=Xx¯,并计算数据的协方差矩阵。我们会得到一个d×d的方阵:

(116)C=1nXTX(117)=[Var(X1)Cov(X1,X2)Cov(X1,Xd)Cov(X2,X1)Var(X2)Cov(X2,Xd)Cov(Xd,X1)Cov(Xd,X2)Var(Xd)]

对角线上的数值Var(Xi)是每个特征的方差;其他位置的值Cov(Xi,Xj)是特征Xi和特征Xj之间的协方差。

因为协方差矩阵C是个方阵,我们对其进行特征值分解:

(118)Cv=λv

v是特征向量,表示数据的主要方向;λ是特征值,表示对应特征方向的重要程度(方差)。对其进行求解:

(119)Cvλv=0(120)(CλI)v=0(121)CλI=0(122)det(CλI)=0

根据特征数量,我们会得到d个特征值,将其逐一带回公式119中,便可求出对应的特征向量。之后,我们选择对应最大特征值的向量,构成特征向量矩阵。假设我们选择k个特征向量构建投影矩阵:

(123)V=[v11v12v1kv21v22v2kvd1vd2vdk]

d是数据集的特征数量,k是我们提取的特征向量的数量。最后我们将原始数据矩阵X投影至新的特征空间得到降维后的数据:

(124)Xnew=XV(125)=[x11x12x1dx21x22x2dxn1xn2xnd][v11v12v1kv21v22v2kvd1vd2vdk](126)=[x11v11+x12v21+...+x1dvd1x11v1k+x12v2k+...+x1dvdkxn1v11+xn2v21+...+xndvd1xn1v1k+xn2v2k+...+xndvdk]

其中,Xnew是降维后的数据,这是一个n×k的矩阵,实现了数据维度从dk的过程。

主成分分析算法的操作代码

在主成分分析部分,我们同样使用鸢尾花数据集进行演示。

PCA算法中,最重要的参数是n_components,即指定要保留的主成分数量(降维后的维度)。如果不指定(None),默认会保留所有主成分。该函数可选值包括,整数(指定保留的主成分个数);浮动值(0到1之间的浮动值,表示要保留的方差比例。比如,n_components=0.95表示选择足够的主成分使得总方差达到95%)。

需要注意的是,PCA和因子分析(Factor Analysis,FA)都用到了降维技术,但二者具有本质区别。PCA的主要目的是数据降维,通过找到数据的主成分来解释数据的主要变化,因此主要关注数据方差。FA的目的是发现潜在因子,试图找到观测变量背后隐藏的潜在变量,因此FA关注的是变量之间的共同方差(因子载荷平方和),即解释变量之间的相关性,而非方差。在方法上,PCA计算数据的协方差矩阵并进行特征值分解,选取主成分;FA计算相关矩阵或协方差矩阵,然后用最大似然法或最小二乘法估计因子载荷矩阵。此外,PCA不能进行旋转,主成分是正交的(主成分之间不相关);FA可以进行旋转,因子之间不完全独立。

LDA主题模型

LDA主题模型的基本原理

(1)LDA主题模型的原理

在朴素贝叶斯算法中我们提到,其核心思想是反推,即通过后验概率反推结果。隐式狄利克雷分布(Laten Dirichlet Allocation,LDA)主题模型的核心思想也是反推,通过后验概率推断隐藏结构

LDA主题模型的核心假设是,每篇文档都包含若干个主题,而这些主题下又都包含着若干个主题词。继而,我们可以通过贝叶斯推断,推测出每篇文档的主题分布(文档-主题矩阵)和每个主题的单词分布(主题-单词矩阵)。换言之,LDA将文档中的词生成过程分解为“文档→主题→词”的层次结构。在这个过程中,主题是个隐变量且服从狄利克雷分布,因此叫做隐式狄利克雷主题模型。

我们举个直观的例子,阐述LDA的生成与推断过程。

假设作者要生成一篇关于“动物”和“植物“的文档。

从上帝视角(作者视角)出发: 首先,作者设定两个主题:topic1—动物;topic2—植物;两个超参数:α,控制文档主题的稀疏性(值越大,主题分布越均匀)和β,控制主题词的稀疏性(值越大,主题次分布越均匀)。 其次,作者生成主题-词分布(构造“词袋”):对于每个主题,作者生成一个词分布。例如,topic1的主题词包括了:狮子(0.3)、老虎(0.3)、森林(0.2)、花朵(0.1)等;topic2的主题词包括了:森林(0.2)、花朵(0.3)、树木(0.2)、土壤(0.2)。括号是这些词出现的概率,由狄利克雷分布产生。 再次,假设作者要写一篇“动物在森林中活动”的文档。第一,作者会确定文档主题的比例,比如一篇文档中topic1占70%,topic2占30%。第二,作者从每个主题中选择一些词来形成文章。 最终,这篇文档可能是[“狮子”, “老虎”, “森林”, “花朵”, “森林”]“森林”可能来自Topic 1或Topic 2,这就是语义模糊性)。

然而,现实中读者不知道主题结构和词分布,在他们手中的只有已经成型的文档[“狮子”, “老虎”, “森林”, “花朵”, “森林”]。因此,作者需要从已有文档进行推测。

从凡人视角(读者视角)出发: 首先,读者给每个词分配一个主题,例如[“狮子”(topic1), “老虎”(topic1), “森林”(topic2), “花朵”(topic2), “森林”(topic1)]。 其次,遍历每个词,重新计算它们属于每个主题的概率。例如,第三个词“森林”的当前主题是topic1,但在其他文档中“森林”归属为topic2的频率可能远多于topic1,那么我们按照概率重新分配主题,将第三个词“森林”归类为topic2并更新标签。 最后,经过多轮迭代,得到稳定的主题分配后,计算文档-主题分布(统计文档中每个主题的出现频率)和主题-概率分布(统计每个主题下所有文档中词的频率)。

从上述例子我们能够知道,LDA具有跨文档的语义一致性(比如,在所有文档中“森林”在Topic2出现100次,在Topic1出现0次。即便某文档暂时将“森林”分配到Topic1,后续采样也会因全局统计而强烈倾向于Topic2)。LDA的核心能力是,通过全局词分布捕捉语义模式。此外,LDA还具有“软聚类”特性,一个词(比如森林)可以属于多个主题,一个文档中可以混合多个主题。以及,在结果上LDA会输出每个主题的代表性词列表(比如,topic1:狮子,老虎,森林)和每个文档的主题权重(比如,doc1:70% topic1,30% topic2)。

Dirichlet
Multinomial
Multinomial
Dirichlet
选定主题后
主题决定词的概率
α: 主题分布超参数
θ: 文档的主题分布
Z: 每个单词的主题分配
W: 生成的单词
β: 主题-单词分布超参数
φ: 主题的词分布

上图是LDA的生成过程(编码)。大致包括三个步骤:

第一,选主题配方。假设每篇文档有一个“主题配方”(主题分布,例如30%主题A+70%主题B),这个配方由Dirichlet分布生成。

第二,按配方选主题。对文档中的每个词,根据主题配方随机选择一个具体主题(比如以30%概率选主题A)。

第三,按主题选词。从选定主题的“词语列表”(词分布,例如主题A中“数据”概率高,主题B中“算法”概率高)中随机选一个词。

下图是LDA的分析过程(解码)。我们实际看到的只有最终的词(比如文档内容是:“数据 算法 模型…”),而LDA的任务是:

第一,推断隐藏变量。通过统计这些词的出现模式,倒推每篇文档的“主题配方”(主题分布)和每个主题的“词语列表”(词分布)。

第二,数学工具。通过变分推断(Variational Inference)或吉布斯采样(Gibbs Sampling)来近似计算后验概率p()

推断
计算后验
计算后验
观察到的文档 W
Z: 主题分配
θ: 文档的主题分布
φ: 主题的词分布
超参数 α
超参数 β

同样举个直观的例子。

生成:假设某人写文章时,心里先想好“用60%科技话题+40%教育话题”,然后按比例选主题,再从每个主题里挑词。

分析:LDA看到最终文章里的词(如“神经网络”“课堂”“GPU”“考试”),就能推断出这篇文章混合了科技和教育主题,并量化比例。

(2)LDA主题模型的数学推导

多项式分布和狄利克雷分布是LDA模型的两个基础。

多项式分布是描述多次独立试验中,不同结果出现次数的概率分布。如果我们进行n次独立的试验,每次试验有k种可能的结果(类别),每个类别的发生概率分别是p1,p2,...,pk,且满足:

(127)i=1kpi=1

那么,事件发生的次数(X1,X2,,Xk)服从多项式分布,记作:

(128)(X1,X2,,Xk)Multinomial(n:p1,p2,...,pi)

其中,Xi表示第i类出现的次数,即某一类别被抽到的次数;n表示总试验次数,即总抽取次数;pi表示第i类发生的概率。多项式分布的概率计算公式如下:

(129)P(X1=x1,X2=x2,...,Xk=xk)=n!x1!x2!...xk!i=1kpixk

其中,x1,x2,...,xk是每个类别被抽到的次数。

例如,我们有一个六面均质的骰子,每面的概率是16。我们抛10次,结果可能是:1出现3次、2出现2次、3出现1次、4出现2次、5出现1次、6出现1次。这个随机变量(X1,X2,X3,X4,X5,X6)服从多项式分布。我们想计算具体事件的概率,可以将其带入公式129。

狄利克雷分布是对“概率分布”本身的分布。假设有k个类别,每个类别的概率p1,p2,...,pk需要满足:

(130)p1+p2+...+pk=1,pi0

换句话说,它描述的是一个k维度的概率向量。我们可以用狄利克雷分布对这些类别概率的不确定性进行建模:

(131)p=(p1,p2,...,pk)Dirichlet(α1,α2,...,αk)

其中,α=(α1,α2,...,αk)是超参数,控制每个类别的先验权重。狄利克雷分布的概率密度函数:

(132)f(p1,...,pk|α1,...,αk)=1B(α)i=1kpiαi1

其中,标准化因子B(α)=i=1kΓ(αi)Γ(i=1k)αiΓ(x)是伽马函数,它是阶乘的推广:Γ(n)=(n1)!

例如,一个袋子里有红黄蓝三种颜色的球,但我们不知道它们的真实比例(p1,p2,p3)。我们用狄利克雷分布来表示我们对它们的先验知识:(p1,p2,p3)Dirichlet(α1,α2,α3)。如果α1=2,α2=2,α3=2,表示我们认为所有颜色的概率大致相等;α1=10,α2=2,α3=2,表示我们更相信红色球的概率更大。假设在我们抽取10个球后,发现有6个红球、2个黄球、2个蓝球,那么后验分布变成了:(p1,p2,p3)Dirichlet(10+6,2+2,2+2)=Dirichlet(16,4,4)。这表示,在有数据更新后我们对颜色比例的认识更加集中了。

假设现在我们有一组数据,其服从多项式分布,即:

(133)P(x|p)i=1kpixk

其中,p=(p1,p2,...,pk)是概率向量,满足i=1kpi=1x=(x1,x2,...,xk)是观察到的计数。假设参数p服从狄利克雷分布,先验分布为:

(134)P(p|α)i=1kpiαk1

根据贝叶斯定理,后验分布正比于似然与先验的乘积:

(135)P(p|x,α)P(x|p)P(p|α)=i=1kpixki=1kpiαk1(136)=i=1kpixk+αk1

这个后验分布是个新的狄利克雷分布:

(137)p|x,αDirichlet(α+x)

换言之,多项式分布与狄利克雷分布具有共轭性(如果后验分布的形式与先验分布相同,那么这个先验分布就被称为共轭先验)。

LDA主要涉及以下符号:

符号含义
D语料库中文档的总数
K主题的总数
Nd文档d的总单词数
V词汇表大小(所有文档中不同单词的数量
wd,n文档d中第n个单词
zd,n单词wd,n的主题标签
θd文档d的主题分布(K维向量
ϕk主题k的词分布(V维向量
α主题分布的狄利克雷先验参数(K
β词分布的狄利克雷先验参数(V

在LDA生成过程中,我们认为每个文档由多个主题混合而成,每个主题又有多个词混合。我们将这个过程想象成活字印刷:每篇文档准备一个主题混合桶θdDirichlet(α);每个主题准备一个词语混合桶ϕkDirichlet(β);写文档d时,从主题桶θd中随机抓取一个主题zd,nMultinomial(θd);根据所选主题zd,n,从词语桶ϕzd,n中随机抓取一个词wd,nMultinomial(ϕzd,n)。直至写完Nd个词。因此,一篇文档生产出来的联合概率(后验概率正比于似然函数与先验概率的乘积):

(138)P(w,z,θ,ϕα,β)=d=1DP(θdα)文档主题先验k=1KP(ϕkβ)主题词语先验d=1Dn=1NdP(zd,nθd)P(wd,nzd,n,ϕ)生成过程(似然函数)

其中,超参数α控制主题分布的稀疏性;超参数β控制词分布的平滑程度。P(ϕβ)P(θα)是狄利克雷分布,分别控制主题-词分布和文档-主题分布。P(zθ)代表主题选择的概率,从θd采样;P(wz,ϕ)代表词选择的概率,从ϕk采样。

LDA的推断目标就是从观测到的词语w中反推出隐变量θ,ϕ,z后,将其带回公式132中,获得文档-主题分布、主题-词分布和参数,主要包括以下任务:主题分配,确定每个词wd,n对应的主题zd,n;参数估计,估计文档主题分布θd和主题词分布ϕk;超参数估计,调整αβ使模型更贴合数据。计算后验概率:

(139)P(θ,ϕ,zw,α,β)=P(w,z,θ,ϕα,β)P(wα,β)

其中,分母:

(140)P(wα,β)=zP(w,z,θ,ϕα,β)dθdϕ

由于无法解析计算,需要通过变分推断(Variational Inference)或马尔科夫链蒙特卡洛(MCMC)方法求解。

变分推断的核心思想是,用一个简单的分布族q(z)逼近真实后验分布p(zw),通过优化缩小两者的差距。具体步骤如下:

第一步,假设隐变量(θ,ϕ,z)之间独立,选择共轭分布(狄利克雷分布)作为变分分布:q(θ,ϕ,z)=dq(θd|γd)kq(ϕk|λk)d,nq(zd,n|ϕd,n)。其中,γd,λk,ϕd,n是变化参数。

第二步,优化证据下界(ELBO)。通过最大化ELBO来优化qELBO=Eq[logp(w,z,θ,ϕ)]Eq[logq(θ,ϕ,z)]。ELBO是真实对数似然的下界,最大化ELBO等价于最小化q与真实后验的Kullback-Leibler(KL)散度。

第三步,交替更新每个变分参数(如文档-主题分布 (γ)、主题-词语分布 (λ))。固定其他参数,更新q(z);固定q(z),更新q(θ)q(ϕ)

第四步,收敛判断,当ELBO的变化小于阈值时停止迭代。

马尔可夫链蒙特卡洛的核心思想是,通过构造马尔可夫链,生成服从后验分布的样本,用样本均值近似期望。常用方法吉布斯采样(Collapsed Gibbs Sampling),边际化掉θϕ后,直接对z采样,继而简化计算。

第一步,随机初始化。为每个词wd,n随机分配一个主题zd,n(0)

第二步,对每个词wd,n,根据当前其他词的主题分配,计算新主题概率:P(zd,n=kz¬(d,n),w)nd,k(¬n)+αk(nd,k(¬n)+α)nk,wd,n(¬n)+βv(nk,v(¬n)+β)。其中,nd,k(¬n)是文档d中分配给主题k的次数(排除当前词);nk,v(¬n)是主题k中词v出现的次数(排除当前词)。

第三步,收敛后统计。丢弃初始的燃烧期样本,用后续采样结果进行估计:θ^d,k=nd,k+αk(nd,k+α)ϕ^k,v=nk,v+βv(nk,v+β)

维度吉布斯采样变分推断
核心思想通过条件概率逐步采样,生成马尔科夫链收敛到后验分布通过优化找到一个最优的近似分布,使其逼近真实后验
方法类型随机采样方法优化
计算方式反复采样直到收敛通过最大化ELBO进行优化
计算效率计算量大,收敛慢,高维时效率低计算量较小,通常比MCMC更高效
适用场景变量较少、计算资源充足,精确推断要求高变量较多、计算资源有限,需要快速近似推断
优点采样得到的分布更准确计算速度快,适用于大规模数据
缺点计算开销大,收敛慢近似分布受限于选定的变分族,可能会损失精度
在LDA中的应用通过吉布斯采样为每个单词分配主题通过变分推断估计主题分布和单词分布

总的来说,LDA主题模型的过程包括:LDA生成过程→LDA的联合分布→求后验分布→采用近似推断。核心步骤如下:

第一步,LDA生成过程。设定超参数,按照LDA生成文档数据(规定好主题数量k→设定好超参数α后从狄利克雷分布中抽取文档的主题分布→设定好超参数β后从狄利克雷分布中抽取主题的词分布→为文档中的每个单词生成主题和单词)。

第二步,LDA的联合分布。建立完整的概率模型,描述变量之间的关系(LDA的目的是推断文档中的主题,即给定单词w,求主题变量z的后验概率)。

第三步,求后验分布。计算主题变量的后验概率,但无法解析求解(分母边际似然P(wα,β)的求解涉及对所有可能的θ,ϕ,z进行积分求和。计算量极大,无法解析求解)。

第四步,采用近似推断。使用吉布斯采样(通过迭代采样主题变量z来收敛到真实的后验分布)或变分推断(将复杂的积分问题转化为优化问题)近似计算主题分布。

LDA主题模型的操作代码

(1)基本流程

我们用一个简单的例子展示LDA如何运行。假设我们现在有五个文档:

文档1:我爱吃麦当劳的炸鸡。 文档2:炸鸡是我最喜欢的食物。 文档3:我喜欢看篮球比赛。 文档4:我经常看NBA。 文档5:打篮球事件很有意思的事情。

从直觉上,我们能察觉这五个文档大致涉及两个主题:食物、体育。我们使用LDA自动发现这些主题,并对其进行动态可视化。

确定主题数量是LDA主题模型的关键。为了找到合适的主题数量,我们一般会计算LDA的困惑度和一致性指标,困惑度较低或主题一致性较高时,说明该主题数适合当前数据。除此之外,超参数的αβ对LDA主题分析也至关重要,它控制着主题分布和词分布的稀疏性。总的来说,LDA调参过程通常涉及以下参数。

num_topics,主题数。LDA最核心的参数之一,决定了模型可以分成多少个主题。主题数一般需要通过试验选择,可以从小到大尝试不同的主题数,然后通过模型的表现(如困惑度、主题一致性等指标)来选择最佳的主题数。

passes,迭代次数。决定了每个文档会被遍历多少次,每一次遍历都会优化模型参数,但也越容易出现过拟合问题。

iterations,单个文档的迭代次数。决定了每个文档在每一轮更新时的最大迭代次数。

alpha,文档-主题稀疏性。控制每个文档涉及到多个主题的程度。如果alpha较大,则每个文档会包含更多的主题;如果较小,则每个文档会集中在较少的主题上。默认值为'symmetric',这意味着每个主题在文档中的分布是均匀的,或每个文档对每个主题的贡献程度是一样的(文档对所有主题的偏好是平衡的);也可以设置为'asymmetric',这意味着每个文档对某些主题的偏好可能更强烈,而对其他主题的偏好较弱;'auto',让模型自动调整alpha,根据文档的特征决定每个文档对各个主题的偏好程度。

beta在Gensim中对应eta),主题-词稀疏性。控制每个主题下涉及到多个词的程度。如果beta较大,则每个主题会包含更多的词;如果较小,则每个主题会集中在少数几个词上。默认值为0.1,表示每个主题对不同词汇的偏好较为均衡。较低的值会导致每个主题偏向更少的词汇,而较高的值会导致主题在词汇上的分布更加均匀;也可设置'symmetric',表示每个主题对词汇的偏好分布是均匀的,所有的词汇在所有主题中有相同的分布;'auto':让模型自动确定beta,根据每个主题的词汇分布来调整先验。

chunksize,指定每次处理的文档数目,可调整每批次处理文档的大小。

workers,指定LDA模型训练时使用的CPU核心数目。

minimum_probability,用于控制词-主题分布中每个单词的最小概率。低于此概率的单词将被丢弃。

(2)调参过程

我们以历年政府工作报告为例,展示LDA的调参过程。

在确定好主题数后,我们使用网格搜索和随机搜索调整其他参数。

我们来对比一下随机搜索。

在调好参数后,我们可将最优参数一并代入模型中,计算主题分布、词分布,并进行可视化(调参→训练→分析)。


神经网络算法

神经网络算法的基本原理

脸盲症

在某次采访中刘强东谈及妻子奶茶妹妹章泽天时,他直言不知妻子漂亮:“我这个人脸盲,就是说我根本分不清楚谁漂亮谁不漂亮。说实话,我跟她在一起不是因为她漂亮,因为我根本不知道她漂不漂亮”。尽管这种说法引来了诸多质疑,但不可否认,现实中的确有部分人无法从人脸中提取出有效特征,看谁都一个样。比如,“流水线”式批发生产的韩国偶像团体。

韩国偶像女团

当然,除了“脸盲”外,有些人可能还患有“路痴”、“失读”等症状。神经网络算法就是帮助我们识别出人工不好提取特征的场景,运用大数据自动推演对象的特征,比如人脸识别、自动驾驶。虽然神经网络是机器学习的一种方法,属于深度学习的一个子领域(深度学习是具有多个隐藏层的神经网络),但它与传统的机器学习算法不同。前面我们介绍的DT、SVM、KNN这些属于传统的机器学习算法,通常依赖于人工特征提取和相对简单的模型,而神经网络,特别是深度学习,能够处理更大规模、更复杂的数据,通过多层的网络结构进行特征的自动学习和抽象,具有更强的表达能力。因此,神经网络本身是一种通用的学习框架,可以应用于有监督学习、无监督学习,甚至强化学习。

神经网络算法的基本原理

在介绍神经网络之前,我们先简单回顾一下高中生物知识。人类大脑是由大量“神经细胞”(Neural Cell)为基本单位组成的庞大神经网络,这些神经细胞又被称作神经元(Neurons),它们相互连接,形成一个高度复杂的网络结构,负责处理各种信息。

生物神经元结构

神经元的结构很简单。中间一只球形的细胞体,一头长出许多细小且茂密的神经纤维分枝(树突),用以接收其他神经元传递的信号;另一头伸出细长的凸起纤维(轴突),用以将自己的信号传递给其他神经元。轴突末端又会分出许多神经末梢,通过突触连接到其他神经元。轴突外部包裹着髓鞘,类似绝缘层,能提高信号的传导速度。髓鞘之间的间隙称为郎飞结(Node of Ranvier),使得神经信号可以跳跃式传导,提高效率。

当大脑思考时,神经元通过电信号和化学信息传递信息,形成复杂的神经活动模式。具体而言,未激活的神经元在静息状态下,细胞膜内外带不同的电压,形成静息电位。这种电位差由钠离子和钾离子差维持着。当神经元收到足够强的刺激(其他神经元传来的信号)后,电压门控钠通道打开,钠离子涌入,导致膜电位快速上升。当膜电位达到阈值时,神经元会被激活,产生动作电位,此时电信号沿着轴突传播,以郎飞结间跳跃的方式迅速前进,提高信号传输速度。神经信号从一个神经元传递到下一个神经元时,会经过突触。信号到达轴突末端,触发钙离子通道开放,突触小泡释放神经递质(如谷氨酸、多巴胺、乙酰胆碱等)。神经递质进入突触间隙,与下一个神经元的受体结合。若刺激足够强,下一个神经元会被激活,产生新的动作电位,继续传递信号。

人工神经网络结构

通过模拟生物神经元的工作原理(接受来自其他神经元的信号→超过一定的阈值后,神经元会被激活,并通过轴突传递信号给其他神经元),人类构建了人工神经网络(Artificial Neural Network, ANN)。简单来说,ANN是对人脑的数学建模,它由许多神经元构成,这些神经元通过连接(权重)形成网络。神经网络的基本构成单元包括:输入层、隐藏层和输出层。

输入层(Input Layer:接收外部数据,每个节点代表数据的一个特征。

隐藏层(Hidden Layer:神经网络的中间层,通常包含多个神经元。它负责通过非线性变换处理输入数据,学习数据中的抽象特征。可以存在许多隐藏层,深度网络正是通过多层隐藏层来构建复杂的特征表示。

输出层(Output Layer:产生最终的预测结果。输出的形式根据任务不同(分类、回归)而有所差异。

人工神经元结构

上图个典型的人工神经元(感知机,Perceptron)。它的工作原理为,人工神经网络中的“神经元”接收输入,计算加权和,并通过激活函数决定是否“激活”输出。具体过程如下:

输入(inputs:每个神经元接收输入信号。假设某个神经元接收到来自上一层神经元的信号x1,x2,...,xn

权重(weight:每个输入信号都有一个对应的权重w1,w2,...,wn,表示输入的重要性。

加权和(weighted sum:神经元对输入信号进行加权求和,并加上一个偏置项b,形成总输入zz=w1x1+w2x2+...+xnxn+b

激活函数

激活函数(Activation Function:加权和z通过激活函数f(z),以非线性方式输出神经元的激活值。这个过程模拟了神经元激活特性。常见的激活函数包括:Sigmoid,将输出限制在(0,1)之间,形式为f(z)=11+ez;ReLU(Rectified Linear Unit),输出z的正部分,负部分为0,形式为f(z)=max(0,z);Tanh,输出范围在(1,1)之间,形式为f(z)=ezezez+ez;Softmax,常用于多分类任务,输出一组概率值。假设一组输出向量z=[z1,zx,...,zn],Softmax函数将其转换成概率分布P=[p1p2,...,pn],形式为pi=eznj=1nezj

举个简单的例子。

假设有个神经元接收到来自上层的三个数据:x1=2,x2=3,x3=4,每个数据的权重是w1=0.5,w2=1.5,w3=0.3 之后机器会对神经元进行加权求和:z=2×0.5+3×1.5+4×0.3=6.3 有时,为了数据平滑我们还会加上一个偏置项,假设偏置项b=0.5,那么最终输入为6.3+0.5=6.8 最后,神经元会对加权和进行激活。假设我们使用的激活函数是ReLU(如果输入大于0,输出该值;否则输出0),最终神经元的输出为ReLU(6.8)=6.8

因此,神经网络是一个向前传播的过程:输入数据从网络的输入层开始,通过每一层神经元,直到输出层。每一层都会进行计算,最终输出一个预测值。这个过程不涉及任何参数更新,只是纯粹的计算。

但我们知道,人类是会犯错的。就像不管老师在课堂上重复过多少次知识点,学生也还是会做错题。机器同样如此。为此,我们需要对神经网络进行训练。

损失函数是训练神经网络的参照,用于衡量神经网络的预测值(向前传播得到的Y^)与真实值Y之间的差异。就像传统机器学习一样,我们的目标是通过不断调整参数(权重和偏置),最小化损失函数。

在阐述GBDT时我们提到了梯度这个概念。梯度是一个向量,表示某个函数在某个点的变化最快的方向。在训练神经网络过程中,我们使用梯度下降法。从输出层开始反推如何调整参数(权重和偏置项)能够使损失函数最小,这个过程又被称作反向传播。之后,我们会获得新的参数,重复前边的步骤(向前传播→损失函数→反向传播→更新参数),直到模型收敛,损失函数达到最小值。

综上所述,神经网络的运作大致经历以下几个步骤:

第一步,向前传播。首先,输入数据(图像、文本或其他特征数据)会被传入神经网络的输入层。其次,数据会对每一层的神经元进行处理。在每一层:每个神经元会对输入数据进行加权求和,并加上偏置项;通过激活函数(ReLU、Sigmoid、Tanh等)对结果进行非线性变换,产生该层的输出。最后,数据会从最后一层(输出层)得到网络的预测结果。

第二步,计算损失。在向前传播过程中,网络会输出一个预测值(例如,分类问题中的预测标签或回归问题中的预测值)。之后,通过损失函数(如回归问题中的MSE或分类问题中的交叉熵损失)计算预测值与真实值之间的差异。损失值越小,说明模型的预测越准确;损失值越大,说明预测偏差较大。

第三步,反向传播。反向传播是计算每个参数(权重和偏置)对损失函数的影响程度的过程。通过链式法则,反向传播将损失从输出层传递到输入层。对于每一层,反向传播计算该层的梯度(损失函数对该层权重和偏置的偏导数),表示该层参数调整的方向和大小。这个过程会逐层计算每个参数对总损失的贡献,直至网络的第一层(输入层)。

第四步,更新参数。使用梯度下降法或其他优化算法(如Adam、RMSprop等)更新权重和偏置,这个过程通过沿着梯度的反方向调整参数。

第五步,重复迭代。以上步骤会不断重复多次,直至模型收敛。每次迭代都会根据当前数据调整模型参数,使模型的预测结果愈发准确。

简单来说,这是个不断调整权重和偏置,使神经网络能够做出准确预测或分类的过程

神经网络算法的数学推导

神经网络的核心包括前向传播、损失函数、反向传播和梯度下降。我们从最基本的神经元开始,逐步推导整个神经网络的计算过程。

(1)神经元的数学模型

参照生物神经元中信号传递的特性,单个人工神经元的数学表达式如下:

(141)z=WX+ba=f(x)

其中,X是输入向量,X=[x1,x2,...,xn],输入数据可以是图片像素也可以是词向量。W是权重矩阵,即神经元的可学习参数。W=[w1,w2,...,wn]b是偏置项,用于调节输出的参数。z是线性变换结果。f(z)是激活函数,通过非线形变换使神经网络具备表达复杂函数的能力。

(2)神经网络的前向传播

假设我们有个三层的神经网络:第一层,输入层X;第二层,隐藏层H通过ReLU函数激活);第三层,输出层Y通过Sigmoid函数激活)。

第一层的计算:

(142)Z1=W1X+b1A1=f(Z1) (RuLE:f(x)=max(0,x))

第二层的计算:

(143)Z2=W2A1+b2A2=g(Z2) (Sigmoid:g(x)=11+ex)

最终输出结果为:

(144)Y^=A2

(3)损失函数

损失函数衡量预测值Y^和真实值Y之间的误差。常见的损失函数包括:

均方误差(MSE,常用于回归):

(145)L=1mi=1m(yiy^i)2

交叉损失熵(Cross Entropy Loss,常用于分类):

(146)L=1mi=1myilog(y^i)+(1yi)log(1y^i)

(4)反向传播

为了更新参数Wb,需要计算损失对它们的偏导数,即:

(147)LW,Lb

首先,计算损失函数对输出层预测值的偏导数,表示输出层误差对损失的贡献:

(148)LA2=Y^Y

接下来,从输出层开始,逐层反向传播误差,通过链式法则计算每一层的权重梯度:

(149)LW=LAAZZW

其中,LA是上一层的梯度;AZ是激活函数的导数;ZW是线性变换对权重的偏导数。

在例子中,输出层的梯度权重:

(150)LW2=LA2A2Z2Z2W2

隐藏层的损失函数梯度计算:

(151)LA1=LZ2Z2A1=LZ2W2

隐藏层的权重梯度:

(152)LW1=LA1A1Z1Z1W1

最后,计算每一层的偏置项梯度。

输出层的偏置项梯度:

(153)Lb2=LZ2Z2b2=LZ2

隐藏层的偏置项梯度:

(154)Lb1=LZ1Z1b1=LZ1

我们会发现,偏置项梯度就等于损失函数对当前层的预激活值(激活函数输入)的梯度:

(155)Lbi=LZi

(5)梯度下降

计算完梯度后,更新参数:

(156)W=WηLW(157)b=bηLb

其中,η是学习率,用于控制更新幅度。

Y^是模型预测输出,Y是真实标签,δi是第i层的偏置项(LZi),η是学习率,σ是激活函数。

参数更新
反向传播
前向传播
W1, b1
σ
W2, b2
σ
反向传播
链式求导
计算梯度
传播误差
计算梯度
更新
更新
更新
更新
生成损失
更新参数
更新后继续训练
W1 = W1 - η ∂L/∂W1
b1 = b1 - η ∂L/∂b1
W2 = W2 - η ∂L/∂W2
b2 = b2 - η ∂L/∂b2
∂L/∂a2
δ2
∂L/∂W2
∂L/∂b2
δ1
∂L/∂W1
∂L/∂b1
Z1 = W1 * X + b1
输入 X
a1 = σ(Z1)
Z2 = W2 * a1 + b2
a2 = σ(Z2)
Loss(Ŷ, Y)

前馈神经网络算法

FNN(Feedforward Neural Network, FNN)是最基本的神经网络形式。它由输入层、隐藏层和输出层组成。信息从输入层开始,经过每一层的神经元计算后,最终到达输出层。每一层的神经元只与相邻层的神经元连接,信息没有回流

基本理论部分我们已展开详细论述,本章将不再赘述。接下来,我们会分别使用sklearn模块自带的糖尿病数据集和葡萄酒数据集,展示FNN如何处理回归任务和分类任务。

前馈神经网络的回归问题

(1)基本模型

一般而言,基本的FNN需要经过几个步骤:加载数据→搭建神经网络→编译模型→训练模型→预测模型→模型评估与结果可视化。

我们以糖尿病数据库为例,通过神经网络来预测糖尿病的进展程度。

为了提高预测性能,FNN可以调整的超参数包括:

隐藏层数量、神经元数量、激活函数。常见的激活函数有ReLU、Sigmoid、Tanh等。ReLU通常是最常用的激活函数,特别适用于深度网络;Sigmoid和Tanh函数常用于二分类问题,但可能导致梯度消失问题,也尝试使用Leaky ReLU(避免ReLU中的“死神经元”问题)。回归任务中,可在输出层使用线性激活函数activation='linear'

调整优化器和学习率。FNN默认的学习率是0.001,需要引入optimizers模块进行调整。也可以指定优化器,常用的有SGD(随机梯度下降),Adam,RMSprop等。

调整批量大小。batch_size决定了每次权重更新时使用多少训练样本。较小的批量大小通常会带来更好的泛化能力,但可能训练较慢;较大的批量大小训练更快,但可能不太容易找到全局最优解。常见的批量大小选择:32,64,128。

训练轮次。Epochs决定了模型学习的次数。可以在训练过程中监控损失(loss)和验证损失(val_loss),以适时停止训练(使用EarlyStopping回调函数)。通过EarlyStopping模块提前结束循环,防止模型过拟合。设置好EarlyStopping后在model.fit()部分加入callbacks=[early_stopping]。 

正则化。为了防止过拟合,可以使用正则化L1(适用于稀疏特征)、L2(适用于过大的权重),以及Dropout(丢弃神经元)。

(2)网格搜索

我们用网格搜索来演示FNN的调参过程。由于GridSearchCV只适用于sklearn模块,我们进行手动遍历。

前馈神经网络的分类问题

(1)基础模型

在前馈神经网络的分类问题中,我们使用sklean模块自带的葡萄酒数据集作为示例。该数据集包含红酒的各种化学特性(酒精含量、酸度、pH值、残糖量等,一共13个特征),标签表示葡萄酒的质量等级(class1、class2、class3,一共3个等级)。

(2)随机搜索

在分类问题的超参数调整部分,我们同样使用葡萄酒数据进行演示。在方法上,我们手动进行随机搜索。

卷积神经网络算法

卷积神经网络的基本原理

(1)卷积神经网络的原理

卷积神经网络(Convolutional Neural Network,CNN)是一种专门用于处理图像数据的深度学习模型,它能够自动提取特征并用于分类、检测等任务。它的核心思想是模仿人类视觉系统,通过“局部感受”和“逐层提取特征”来理解图像内容

举个直观的例子。

假如我们修一张自拍照。我们首先会去微调五官轮廓(修眉),然后去除脸部瑕疵(祛斑、痘印),接着调整脸部比例(瘦脸),再然后添加各种滤镜(提升美感),最后输出照片。

这个修图的过程就是CNN进行识别的过程。

CNN处理图片的方式修图的方式作用
卷积层:提取局部特征(边缘、纹理等微调五官轮廓(修眉强化局部特征,让重要特征更明显
ReLU激活:去掉无关信息去除瑕疵(痘印、斑点去掉无关或无用的细节
池化层:降低分辨率,减少不重要信息整体调整比例(瘦脸、调整脸型去掉细枝末节,保留整体结构
多层卷积+池化:逐步抽象出更高级特征综合调整(五官协调、添加滤镜提升全局效果,得到最终美学特征
全连接层:最终决策(识别是猫还是狗最终效果(颜值评分、是否变美输出最终结果

因此,CNN主要包括四个核心结构:卷积层:提取局部特征,浓缩信息;激活函数层:增加非线性,去除无关信息;池化层:降维和保持重要信息,降低计算量;全连接层:将所有信息压缩成一个固定长度的向量,输出结果。

卷积神经网络基本结构

卷积层(Convolutional Layer

卷积层是CNN的核心,其作用是识别图像中的局部特征(边缘→纹理→形状),保留空间关系并逐步提取更多抽象的特征。卷积核是卷积的重要概念,这是一个小型矩阵,用来滑动扫描整个图像,并计算点积。如下图所示,其作用类似于滤波器,通过对图像扫描识别出不同的特征。

卷积核

举个例子。

假设我们输入一个5×5的灰度图像,我们有个3×3的卷积核。

这相当于我们对于左上角的特征提取值为-12。接着,我们可以继续从左至右,从上至下滑动卷积核,依次扫描图像并计算每个部位的特征。步长决定了卷积核在图像上滑动的步幅,步长=1表明每次移动1个像素;步长=2表示每次滑动2个像素。

填充是卷积过程的又重要概念。在上述例子中,如果我们以步长为1进行扫描,最终会将图像由5×5变成3×3。为了保持特征图的尺寸,同时让边缘的像素也能被充分学习,不至于图像越卷积越小,我们会对图像边缘进行填充。最常见的方式如下面展示的,在图像周围填充0。一般来说,要保证卷积滑动后输出尺寸与原图相同,填充大小P=K12,其中K是卷积核大小。

总言之,卷积层就是个放大镜,第一层卷积像是在初步检查,拿着放大镜识别边缘和简单形状;中间层卷积像拿着专业放大镜,识别更为复杂的纹理和角落;深层卷积则是AI分析,能够识别人类、物体等高级特征。

激活函数层(Activation Function Layer

激活函数的概念我们之前提及过,在CNN中重点介绍它的作用。图像在经过卷积层后,会返回一组线性变换后的特征图。但现实世界中的图像往往具有非线性特征,因此激活函数的作用就是引入非线性,让CNN具备学习复杂模式的能力,增加模型的表达能力,避免只是简单的加权计算。同时,由于激活函数经常为ReLU、Leaky ReLU、Sigmoid、Tanh等,因而可以去除无用信息(负值变为0),突出重要特征。

激活函数公式适用场景优缺点
ReLUf(x)=max(0,x)卷积层最常用计算快,但可能导致“死亡”神经元
Leaky ReLUf(x)=x/0.01x改进ReLU允许负值信息通过,解决死亡问题
Sigmoidf(x)=11+ex二分类任务梯度消失,不适合深度网络
Tanhf(x)=exexex+ex深度网络但不太深均值为0,但梯度可能消失
Softmaxexex最终分类层转换成概率分布

池化层(Pooling Layer

在经过卷积层和激活函数层之后,有些特征映射的维度依旧很高,这时就需要通过池化层进一步降低数据维度,保留关键信息。换言之,池化层的主要作用是——减少计算量:降低特征图的尺寸,减少参数,提高计算效率;增强特征稳健性:避免模型对微小的位移、旋转、缩放过于敏感;降低过拟合风险:保留主要特征,去除冗余信息。

池化层

池化窗口是指每次池化区域的大小,如上图中展示的2×2窗口。常见的池化层有最大池化(Max Pooling)和平均池化(Average Pooling)两种。最大池化就是取池化窗口中最大的数值;平均池化通过平均池化窗口中的数值获得。直观来说,池化的作用就是压缩像素(如图中的4×42×2),在这个过程中最大池化像是“智能剪裁”,保留最关键的信息;平均池化像“降低整体分辨率”,让图片更小但依旧能够看清整体。

全连接层(Fully Connected,FC

全连接层往往是CNN的最后几层,它的作用是把卷积层和池化层提取出的特征合并,从而转换成最终的分类或回归结果。

全连接层

比如说,我们通过卷积层和池化层将猫猫的特征都提取出来了。但此时的特征依旧是多维度的,光凭头、脸、爪子、身体我们仍旧无法明确知道图像是否是只猫。因此,我们需要像拼图一样,将这些特征展开,然后使用神经元进行最终的分类或回归(这些特征组合在一起的究竟是不是一只猫猫)。

换句话说,全连接层的本质就是普通的神经网络(MLP)。首先,将CNN输出的多维度特征展平成一个一维向量;然后,以该向量作为输入,连接多个神经元,每个神经元都有可训练的权重和偏置;最后,通过线性变换(激活函数),进行有效分类或回归。

我们举个直观的例子,逐步拆解CNN的运作流程。

假设现在要识别一张图片是猫还是狗,这是张5×5的灰度图。我们构造一个极简的CNN结构:

输入层:1×5×5通道、高、宽 卷积层:1个3×3的滤波器,步长为1,无填充 激活函数层:ReLU激活 池化层:2×2池化窗口,最大池化,步长为1 全连接层:输出2类(猫或狗

第一步,卷积计算

假设输入矩阵为:

滤波器权重为1:

偏置项为0.5。

以左上角3×3区域为例,其与滤波器的点积为0.1×(1)+0.3×0+0.2×1+0.7×(1)+0.4×0+0.9×1+0.3×(1)+0.6×0+0.8×1=0.9。加上偏置项,0.9+0.5=1.4。通过滑动步长为1的卷积核,我们最终得3×3的特征图。

第二步,ReLU激活

将特征图上所有负值赋零。例如,某个位置的数值为-0.3→0;1.4→1.4。

第三步,最大池化

2×2窗口中的最大值,例如:

继而特征图从3×32×2

第四步,全连接层

将这个2×2特征图展平成一维向量X=[3,2,1,4],连接至2个输出点:k=i=14(wkixi)+bk。其中,wki是每个神经元的权重,W1=[0.5,0.3,0.8,0.2]W2=[0.1,0.2,0.1,0.4]xi是4个神经元的特征;bk是偏置项,b1=0.1b2=0.2

经过计算,dog=3×0.5+2×(0.3)+1×0.8+4×(0.2)+0.1=1.0cat=3×0.1+2×0.2+1×(0.1)+4×0.4+0.2=2.4

第五步,Softmax输出

将2个输出值带入Softmax激活函数中,得到分类的概率。

Softmaxdog=e1e1+e2.40.1978Softmaxcat=e2.4e1+e2.40.8021

最终,图像是狗的概率为19.78%;猫的概率为80.21%。

当然,上述例子只是个最简单的CNN。实际上,我们在面对高维数据时,常常需要设置多个卷积层与池化层,重复进行卷积与池化,在保留核心特征的同时不断缩小尺寸。例如一张224×224×3的图片(3表示RBG彩色通道),就需要经过多层次的降维。

作用输出尺寸
输入图像原始图片224×224×3
卷积+ReLU提取低级特征(边缘224×224×64
池化降维&过滤信息112×112×64
卷积+ReLU提取中级特征(形状112×112×128
池化继续降维56×56×128
卷积+ReLU提取高级特征(局部结构56×56×256
池化再次降维28×28×256
全连接层最终分类1×1×1000

总的来说,CNN的运作流程可以简单概括成:输入图像→卷积层(提取局部特征)→激活函数层(增加非线性)→池化层(降维)→重复多层卷积和池化(提取更高级特征)→全连接层(将特征映射到类别空间)→预测结果。

(2)文本卷积神经网络

文本卷积神经网络(TextCNN)是一种基于CNN的文本分析方法,其核心思想是利用卷积操作提取文本的局部特征,之后通过池化层降维,最终通过全连接层进行分类。TextCNN的整体流程和CNN处理图像基本一致,只是将输入从图像转变成了文本。具体来说:

输入层:使用Word2Vec、GloVe或BERT预训练嵌入模型,将输入的文本转变成词向量矩阵。假设文本长度为n,每个词用d维度向量表示,从而形成矩阵Input Matrix=(n×d)。举个例子:

句子:我喜欢自然语言处理。

将每个词都用300维的词向量表示,整个句子为:

(158)[(300)(300)(300)(300)(300)]

这个5×300的矩阵就相当于一张文本图像。

卷积层:通过多个卷积核滑动窗口扫描文本,提取局部特征。不同的卷积核大小可以捕获不同尺度的语义信息,在TextCNN中,卷积核窗口大小为N-gram,这是NLP的一种方法,指连续N个词组成的字序列,用于分析文本结构。1-gram(Unigram)表示每个单词作为一个单位,2-gram(Bigram)表示每两个连续单词作为一个单位,3-gram(Trigram)表示每三个连续词作为一个单位。以此类推,还能拓展到4-gram、5-gram等等。例如“我喜欢自然语言处理”,在1-gram为[我,喜欢,自然,语言,处理];在2-gram中为[我喜欢,喜欢自然,自然语言,语言处理];在3-gram为[我喜欢自然,喜欢自然语言,自然语言处理]。因此,N-gram能捕捉上下文信息,更好反应语义。这个过程与CNN一致,通过公式Hi=f(WXi)+b计算卷积,其中Xi是滑动窗口内的词向量;W是卷积核权重;b是偏置项;f()是激活函数。同样举个例子:

假如我们现在需要对“我喜欢自然语言处理。”这句话进行情感分析。 我们现在有2个1×300的卷积核,W1=[(300)]W2=[(300)]

通过在文本上分别滑动两个卷积核,我们能得到一组情感特征。H=f(W1Xi+b)H=f(W2Xi+b)

池化层:将卷积层输出的特征进行降维,常见的方法同样是最大池化和平均池化。

全连接层:将池化层输出的向量传递至全连接层,输出最终分类结果。

结构CNN(图像TextCNN(文本
输入层图片(二维矩阵词向量矩阵(一维序列
卷积层2D卷积(如3×3×3滤波器1D卷积(如2×300或3×300滤波器
激活函数ReLUReLU
池化层2D池化1D池化
连接层Flatten(展平)后传入FC层Flatten(展平)后传入FC层
输出层预测类别(如1000类预测情感类别(如2类:积极/消极

总的来说,TextCNN可以算是特殊简化的CNN,只需要一维卷积核(本质上是一个词向量,只是我们将其拉长成二维形状)。因此,TextCNN的卷积计算更简单,只需要沿着词序列滑动卷积核(一个词向量一个词向量的滑动,我→喜欢→自然→语言→处理),而不需要考虑纵向滑动。此外,因为卷积提取后的特征仍旧是一维的,所以池化方式也更简单,可以直接对文本做全局池化(Global Max Pooling),提取全文本最重要的特征。

卷积神经网络的操作代码

(1)卷积神经网络(图像)

我们使用sklearn自带的手写数字集digits进行演示。这是一个包含了8x8像素的手写数字图像,每个图像表示一个0到9的数字,一共拥有1797张灰度图。我们通过CNN来识别每个图像上面的手写数字。

(2)卷积神经网络(文本)

在卷积神经网络部分,我们使用keras模块自带的imdb电影评论数据进行情感分析。该数据集包含了50000条评论,每条评论都是一个句子或一组句子,内容涵盖各种电影类型,每个评论都有一个情感标签,标记为正面或负面(0或1)。在训练好模型后,我们对随机生成的20条评论打上情感标签。

(3)参数调整

总体而言,CNN和TextCNN的调参方式与FNN一致,一般从六个关键部分入手:卷积层参数,卷积核大小、数量、步长、填充;池化层参数,池化方式、窗口大小;优化器和学习率,默认的学习率是0.001,优化器一般为SGD、Adam、RMSprop等;网络结构,层数、神经元数量;正则化,dropout和L2;批量大小和训练轮次,batch_size和epochs。

CNN的调参思路大致为:确定卷积层结构,调整优化器和学习率→尝试不同的卷积核数量和池化方式→使用dropout或者L2进行正则化。

超参数作用调参建议
卷积核大小控制特征提取的局部感受野3×3,5×5
卷积核个数增加能提取的特征数量32,64,128
步长控制滑动窗口的移动步长1,2
填充影响输出尺寸(SAME保持尺寸/VALID减少尺寸SAME/VALID
池化方式降维&保留主要特征Max Pooling,Avg Pooling
学习率控制梯度下降步长0.001,0.0005,0.0001
优化器影响梯度更新方式Adam,SGD,RMSprop
Dropout防止过拟合,丢弃部分神经元0.3-0.5
批量大小控制每次训练的样本数32,64,128
训练轮数影响模型训练的时间&收敛性10-50

TextCNN的调参思路大致为:确定词向量维度和预训练方式,调整卷积核大小和个数→观察池化方式对性能的影响→调整优化器和学习率,找到最佳收敛速度→适当增加dropout以防止过拟合。

超参数作用调参建议
词向量维度影响词的表达能力100,200,300
词向量预训练是否使用预训练词向量(如 Word2Vec、GloVeTrue/False
卷积核大小提取不同N-gram特征2,3,4,5
卷积核个数增加通道数,提取更丰富特征100, 150,200
池化方式降维&保留重要信息Global Max Pooling
优化器影响梯度更新Adam,RMSprop
学习率控制收敛速度0.001,0.0005,0.0001
Dropout防止过拟合0.3-0.5
批量大小影响训练稳定性32,64,128
训练轮数影响模型的收敛情况5-20

递归神经网络算法

递归神经网络的基本原理

(1)递归神经网络的原理

递归神经网络(Recursive Neural Nest work,RNN)是一种专门处理序列数据的神经网络,它的设计使得信息成能够存储在序列中,处理输入数据之间的时序依赖。与传统的前馈神经网络不同,RNN通过循环连接让当前的输出不仅依赖于当前输入,还与之前输出相关联。

递归神经网络基本结构

如图片展示,RNN的核心特点是隐藏层的“循环”结构,它允许网络在处理每个时间步时,将上一时刻的隐藏状态(记忆)传递到下一时刻。这使得RNN能够捕捉输入数据中的时间依赖关系。

我们举个直观的例子。

如果我们知道上个星期的天气情况,就能预测星期一的天气。

实际上,RNN的整体架构与FNN完全相同(输入层、隐藏层、输出层)。唯一区别仅在于隐藏层的构造上。具体来说,RNN的每个时间步t都会收到两个输入:当前时间步的输入xt和上一时刻的隐藏状态ht1

时间步是RNN中的重要概念,指序列数据中每个数据点出现的时间位置或顺序。在处理序列数据时(例如文本、时间序列数据、语音数据等),每个数据点(如一个单词、一帧图像、一秒钟的语音)在时间上都是有顺序的,时间步就是在这个序列中标记的“每一时刻”。比如说,在一个星期中,每天的天气就对应一个时间步。

我们假设输入序列是一组向量X=[x1,x2,...,xT],每一个xt都是时间步t的输入。因此,传统的前馈神经网络可以表示成:

(159)ht=f(Whxt+bh)

其中,Wh表示输入到隐藏层的权重矩阵;bh是偏置项;f()是激活函数。而在递归神经网络中,会保留上一时刻的隐藏状态ht1

(160)ht=f(Whxt+Uhht1+bh)

其中,Uh是上一时刻的隐藏状态到当前隐藏层的权重矩阵。

这个公式的核心思想是,当前的隐藏状态ht由当前输入xt和上一时刻的隐藏状态ht1共同决定(记忆)。所以,RNN的输出也可以基于当前的隐藏状态:

(161)yt=Wyht+by

其中,yt是当前时刻的输出,Wy是隐藏状态到输出的权重矩阵,by是输出的偏置项。

见于RNN的计算并不是单独的,而是一个序列的处理过程,在每一个时间步t,RNN都会根据当前输入和历史状态来更新隐藏状态,并计算输出。我们可以将整个RNN模型通过时间展开:

(162)h1=f(Whx1+Uhh0+bh)(163)h2=f(Whx2+Uhh1+bh)(164)...(165)ht=f(WhxT+UhhT1+bh)

由于RNN的隐藏结构是递归的,因此在计算梯度和权重时,我们使用反向传播通过时间(Backpropagation Through Time,BPTT)。BPTT的核心思想是将RNN看作一个深度神经网络,在时间维度上展开,从而对每个时间步的权重进行更新。与传统的反向传播只计算最终输出与实际目标值之间的差距不同,BPTT对每个时间步的输出(yt)与实际值之间的差距进行反向传播,并逐层计算梯度,最终更新网络中的权重:

(166)Lht=Ltht+k=tTLkhkhkhk1(167)LWh=k=tTLhthtWh(168)Wh=WhηLWh

其中,Lht表示损失函数L对隐藏状态ht的梯度。Lkhk表示在时间步k处,损失函数对隐藏状态hk的梯度。hkhk1表示隐藏状态hk对上一个隐藏状态hk1的梯度,表示时间步k的隐藏状态如何依赖于上一个隐藏状态hk1

我们举个例子,展示RNN的运作过程。

假设我们有一个2个时间步的RNN,并使用激活函数tanh。

在这个RNN中,输入权重W=0.5;隐藏状态权重为U=0.3;输出权重V=0.7;偏置项b=0;学习率eta=0.01

在第一个时间步中,我们的输入x1=1,目标输出y1(true)=0.2;第二个时间步中,输出x2=0.5,目标函数y2(true)=0.4

其网络结构如下:

首先,我们计算向前传播。我们使用tanh激活函数:

(169)ht=tanh(Wxt+Uht1)yt=Vht

其中,初始隐藏状态h0=0

第一步(t=1

(170)h1=tanh(0.5×1+0.3×0)=0.462y1=0.7×0.462=0.323

第二步(t=2

(171)h2=tanh(0.5×0.5+0.3×0.462)=tanh(0.25+0.1386)=0.37y2=0.7×0.37=0.259

接着,我们进行反向传播(BPTT

第一,计算损失。我们使用MSE:

(172)L=12(y1y1(true))2+12(y2y2(true))2(173)=12((0.320.2)2+(0.2590.4)2)(174)=0.0175

第二,我们计算每个输出层的梯度。

(175)L1y1=y1y1(true)=0.3230.2=0.123(176)L2y2=y2y2(true)=0.2580.4=0.141

第三,计算每个隐藏层的梯度。

(177)L1h1=L1y1y1h1=y1y1(true)V=0.123×0.7=0.0861(178)L2h2=L2y2y2h2=y2y2(true)V=(0.141)×0.7=0.0987

第四,计算隐藏状态的梯度。

在图中可知,目前只有一个隐藏状态(h1)。参照公式166:

(179)Lh1=L1h1+L2h2h2h1

其中,根据tanh函数的特征ddxtanh(x)=1tanh2(x)

(180)htht1=(1tanh2(x)U)=(1ht2)U

继而:

(181)Lh1=0.0861+(0.0987)×(10.372)×0.3=0.0605

然后根据公式167计算权重的梯度。

同样,根据tanh函数特性:

(182)htW=(1ht2)xt(183)h1W=(1h12)×x1=(10.4622)×1=0.787(184)h2W=(1h22)×x2=(10.372)×x2=0.431(185)LW=Lh1h1W+Lh2h2W(186)=0.0605×0.787+(0.0987)×0.431=0.0051

最后,根据公式168计算新的权重。

(187)W=0.50.01×0.0051=0.4999

(2)长短时记忆网络

在公式推演部分我们提到,RNN采用BPTT进行权重更新。对于每一个隐藏状态的梯度,我们以链式法则展开:

(188)Lht1=Lhththt1=LhtUh

我们继续将梯度传递回上一层:

(189)Lht2=Lht1Uh=LhtUh2

以此类推,直到达到最初状态h0

(190)Lh0=LhtUht

假设Uh的特征值小于1,那么随着时间步t的增加,梯度会快速变小,直到tUht0,陷入梯度消失的问题。

举个直观的例子。

假设我们在玩传话游戏。第一个人知道一个消息,然后他把消息传递给第二个人,第二个人再传递给第三个人,以此类推,最后传到最后一个人。在这个过程中,每个接收到消息的人都会对消息进行“修改”或者“失真”,导致传递的人数越多消息变得越不准确。

长短时记忆网络(Long Short-Term Memory Networks,LSTM)是RNN的改进版本,在其基础上引入了长期记忆的概念——记忆单元(Ct)。记忆单元是信息流的主干,允许信息在不同时间步之间传递。这些信息在计算过程中可以自由流动,梯度沿着记忆单元传递而不会消失。

其核心思想是在输入与输出之间设置四个门(遗忘门、输入门、候选记忆单元、输出门)以控制信息的流动和记忆单元的更新,通过LSTM有效记住重要信息并遗忘无关信息,从而克服传统RNN中的梯度困境,捕捉更长时间的依赖关系。

遗忘门(Forget Gate

遗忘门决定了我们要“忘记”上一时刻的记忆有多少。它接受当前输入xt和上一时刻的隐藏状态ht1,并输出一个介于0和1之间的数值用以控制保留信息的多少。其公式为:

(191)ft=σ(Wf[ht1,xt]+bf)

其中,ft是遗忘门的输出,控制上一时刻信息的保留比例;σ是Sigmoid激活函数,将输出值范围控制在[0, 1]之间;Wf是遗忘门的权重矩阵,包括隐藏状态权重和输入权重;bf是偏置项。

如果ft的数值接近0,表示“忘记”大部分之前的信息;接近1则表示“保留”几乎所有信息。

输出门(Input Gate

输出门决定当前输出xt中有多少信息会被添加到记忆单元。它的作用是对当前输入进行筛选,决定哪些信息可以更新到记忆单元。公式为:

(192)it=σ(Wi[ht1,xt]+bi)

其中,it是输出门的输出,控制当前输入信息的存储比例;Wi是输出门的权重矩阵,包括隐藏状态权重和输入权重;bi是偏置项。

候选记忆单元(Candidate Memory Cell

候选记忆单元是对当前时间步t输入的候选记忆,通过tanh函数产生,用以表示被添加进记忆单元的“候选信息”。公式为:

(193)Ct~=tanh(WC[ht1,xt]+bC)

其中,Ct~是候选记忆单元,通过激活函数tanh来生成范围在[-1, 1]之间的输出。

更新记忆单元(Cell State Update

记忆单元的更新是通过将遗忘门的输出与上一时刻的记忆单元相乘,再将输入门控制的候选记忆与输入的相关信息加权求和来完成的(保留当前的有用信息,遗忘上一时刻的无用内容)。更新的记忆单元Ct可以将当前时间步的长短期信息进行记忆。

(194)Ct=ftCt1+itCt~

其中,Ct是当前时刻的记忆单元,用于存储重要信息;Ct1是上一时刻的记忆单元。

输出门(Output Gate

输出门决定了从记忆单元中输出多少信息,生成最终的隐藏状态ht作为当前时间步的输出。

(195)ot=σ(Wo[ht1,xt]+bo)(196)ht=ottanh(Ct)

ot是输出门的输出,用于控制从记忆单元输出多少信息;ht是当前时刻的隐藏状态,作为RNN的输出结果。

LSTM的整体结构大致如上。在RNN的基础上,输入xt和上一时刻的隐藏状态ht1会被传入LSTM→遗忘门(ft)和输入门(it)分别决定遗忘上一时刻记忆单元中的哪些信息Ct1和将多少新信息Ct~加入到当前记忆单元Ct中(候选记忆单元通过产生候选记忆信息,供输出门使用)→记忆单元Ct由上一时刻的记忆和当前输入门控制的信息共同更新→输出门ot控制从记忆单元中提取多少信息,并产生当前时刻的隐藏状态ht,这也是LSTM的输出。

举个直观的例子。

同样是传话游戏。记忆单元就相当于一个信封,可以用来存储信息。信封在LSTM中会随着时间步传递,即从一个人传递到另一个人。在这个传递过程中,封信的内容不会被轻易改变,而是通过遗忘门和输出门控制哪些信息应该保留哪些信息应该修改。最终,封信的内容能够稳定地传递,不会因为时间步数增加而失去重要的信息。

我们从数学推导的角度解释LSTM梯度不会消失的原因。

本质上,记忆单元决定了输出结果,因此记忆单元对损失的梯度为:

(197)LCt=LhthtCt=Lhtot(1tanh2(Ct))

根据公式194可知,LSTM的核心特性之一便是记忆单元Ct的数值也会影响每个后续时间步,Ct作为Ct+1的一部分影响未来的损失,因此还需要考虑未来时间步Ct+1反向传播的梯度:

(198)LCt=LhthtCt当前时刻贡献+LCt+1Ct+1Ct未来时刻贡献(199)=Lhtot(1tanh2(Ct))+LCt+1ft+1

继而,记忆单元的梯度不仅依赖于当前的ht,还依赖于下一时刻的梯度LCt+1。这让信息能够在时间步之间流动,避免了梯度在反向传播中快速消失。同时,因为遗忘门ft+1和输入门ot的控制作用,LSTM中的梯度不会因为梯度的连乘而迅速衰减,能够长期保持稳定。

递归神经网络的操作代码

(1)递归神经网络(预测

由于RNN是专门处理时序数据的模型,其最主要的应用领域在预测模拟与文本生成,因此我们使用seaborn模块自带的航空旅客数据集进行演示。该数据集记录了1949-1960年间国际航线乘客数量,是时间序列分析的经典数据集。因为传统RNN可能存在的梯度消失问题,我们使用LSTM对航空旅客人数进行预测。

(2)递归神经网络(文本

在写作时,我们经常会使用“虽然,但是”、“尽管,但”等表达转折的连词,比如“你是个好人,但我们不合适”。在传统的情感分析中(TextCNN),由于词汇各自独立,在扫描到“好人”后可能会将该句子粗暴地分类为积极情感,但实际上后一句是个委婉的负面表达。在此情况下,RNN能够凭借着“记忆”的特性同时考虑“好人”和“不合适”两种情感,继而赋予正确的情感得分。实际上,“好坏参半”的评论十分常见,因此LSTM天生适合对文本进行情感分析。和TextCNN相同,我们使用keras模块自带的imdb电影评论数据演示情感分析(可以试着比较一下TexTCNN和LSTM哪个更好),并对随机生成的20条评论附上情感得分。

(3)参数调整

实际上,与其他神经网络模型相同,RNN的参数调整主要涉及三个部分:结构相关参数决定LSTM网络的层数和单元数)、优化相关参数影响LSTM的训练速度和稳定性)、训练相关参数影响LSTM训练效果和泛化能力)。

超参数 作用 调参建议 参数类别
隐藏层单元数(units 控制LSTM的记忆容量,决定学习能力 32, 64, 128, 256 结构相关参数
LSTM层数(layers 叠加多个LSTM层以提高表达能力 1-3(过多可能导致梯度消失)
时间步长(time_steps 影响LSTM看到的序列长度 10-100(视任务而定)
Dropout率(dropout & recurrent_dropout 防止过拟合,分别用于输入和循环连接 0.1-0.5
优化器(optimizer 控制梯度下降的方式 Adam(推荐), RMSprop, SGD 优化相关参数
学习率(learning_rate 控制梯度更新的步长 0.001, 0.0005, 0.0001
梯度裁剪(clipnorm / clipvalue 防止梯度爆炸 0.5, 1.0, 5.0
批量大小(batch_size 影响训练稳定性和计算效率 16, 32, 64, 128
权重初始化(kernel_initializer 影响模型收敛速度 GlorotUniform, HeNormal 训练相关参数
激活函数(activation LSTM内部非线性变换 tanh, relu
损失函数(loss 选择合适的目标函数 回归:MSE(标准回归损失),MAE(对异常值不敏感回归),logcosh(平滑版MSE);
分类:binary_crossentropy(二分类),categorical_crossentropy(多分类且使用one-hot标签),
sparse_categorical_crossentropy(多分类且使用整数标签)
训练轮数(epochs 训练遍数,过大会导致过拟合 10-100
正则化(L1/L2 防止过拟合 0.0001-0.01

总的来说,ANN是一类模仿人脑神经系统的计算模型,通过神经元(节点)层级的连接来学习和处理信息。通常由输入层、隐藏层和输出层组成。根据不同的任务和数据类型,ANN分别演化出了FNN最基础的神经网络类型,信息在网络中单向流动,从输入层通过隐藏层到达输出层);CNN擅长处理图像和视频数据的深度神经网络。CNN通过卷积操作来提取数据中的空间特征,并通过池化层减少计算复杂度);RNN是一类适用于处理序列数据的神经网络。它通过在网络中添加循环连接来保留之前时间步的信息)。

类别前馈神经网络(FNN卷积神经网络(CNN循环神经网络(RNN
主要用途表达一般映射关系处理图像、视频等数据处理时间序列、文本等数据
结构特点每一层的神经元与下一层全连接通过卷积提取局部特征,减少参数具有时间依赖关系,可记忆过去信息
数据输入向量数据(如表格、基本分类任务2D/3D图像数据序列数据(文本、音频、时间序列
权重共享不共享卷积核共享通过时间共享
计算复杂度高,参数众多适中,减少参数但增加计算量高,依赖时间步展开计算
梯度问题正常正常梯度消失/爆炸(传统RNN
优化方法BP反向传播BP+卷积优化BPTT(时间反向传播
适用场景传统分类和回归问题目标检测、图像分类机器翻译、语音识别、文本生成
改进版本深度FNN(MLPResNet、VGG、InceptionLSTM、GRU、Transformer